My task
Force two classes to have the same (or similar) field names (and their types)
Description
I have an entity and Data Transfer Objects (DTO).
How do I force that if someone adds / removes / changes a field in entity, a test will fail, so DTO class matches the entity class by fields names and if possible by fields structure.
class City {
private String name;
private CityDetails cityDetails;
private Mayor mayor;
}
class Mayor {
private String name;
private LocalDate electionFrom;
private LocalDate electionTo;
}
class CityDto {
private String name;
private CityDetailsDto cityDetails;
private MayorDto mayor;
}
class MayorDto {
private String name;
// The client of the end-point of such DTO does not care about the mayor election.
}
CityDetails and CityDetailsDto can be different or not necessary. I would like to have their diff.
Approaches
Using so called diff tool
Let's imagine a diff tool which has input parameters - two objects and output parameter - Map, where Diff is a structure oldValue, newValue. This tool returns difference between input arguments.
public Map<String, Diff> diff(final Object first, final Object second) {
// This is implemented.
return innerDiff(first, second, otherParameters); //
}
public class Diff {
private String oldValue;
private String newValue;
// getters, setters, constructor.
}
// To achieve this, we used Guava Plain map. It works well!
How do I achieve the same for classes. I want to diff two classes and have their fields as difference.
public Map<String, FieldDiff> diff(Class<?> type1, Class<?> type2) {
// How?
}
One idea is to use reflection and iterate though all fields of the class.
How about using toString and compare?
As an alternative, we define toString() methods in both and then compare.
How to do that if some fields are missing?
Serialize into JSON
Similar to the previous one, but serializing both objects into JSON and then compare their classes by json field names. However, if our entity have already annotation DoNotSerializeNulls with is equal to #JsonInclude(JsonInclude.Include.NON_NULL) #JsonIgnoreProperties(ignoreUnknown = true), then how to do that?
References
https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application
Related
Let's assume we have an enum, that represents searchable fields:
enum SearchableFields {
ALL,
FIELD1,
FIELD2,
FIELD3;
}
This enum is displayed via a (combobox) selection inside a GUI. At runtime, I want to evaluate the selection of this combobox and search accordingly.
Depending on the selection, I need to retrieve the fields to search from a POJO (example below) via a getter.
class FieldPojo {
private String field1;
private String field2;
private String field3;
...
public String getField1() {
return field1;
}
...
}
I currently use a switch statement to evaluate the selection of SelectableFields and to then retrieve the correct field(s) to search:
private String retrieveField(FieldPojo f) {
switch (selectedField) {
case ALL:
return retrieveAll(); // method that retrieves all available fields
case FIELD1:
return f.getField1();
...
}
This does work, however I feel like it's clunky.
Question:
Is there a more concise way to do this without evaluating the enum via a switch? (Java 8)
You could store a reference to the getter in your enum constants:
enum SearchableFields {
ALL(FieldPojo::retrieveAll),
FIELD1(FieldPojo::getField1)
private final Function<FieldPojo, String> accessor;
SearchableFields(Function<FieldPojo, String> acccessor) {
this.accessor = accessor;
}
public String get(FieldPojo fp) {
return accessor.apply(fp);
}
}
You can create a static map instead of the switch-case.
private static final Map<SearchableFields,Supplier<String>> searchableFieldsToFieldPojo = Map.of(
ALL, this::retrieveAll,
FIELD1, FieldPojo::retrieveAll
);
And then you can access via:
searchableFieldsToFieldPojo.get(selectedField).get();
Given that you can modify all parts of the code, you have several options:
Put the retrieveField into the class FieldPojo and modify it's parameter so it takes the enum SearchableFields as parameter.
Put the fields of FieldPojo as values into a map with a key of type SearchableFields. You can then decide whether you want to have "ALL" as an extra entry of the map or handle it as special case in a method similar to retrieveField. You could use this to have a "default" handling if you want to update the enum but not the FieldPojo class.
You put retrieveField into the class FieldPojo together with the SearchableFields enum - since only FieldPojo knows, which fields it actually provides as searchable fields.
You use introspection to gather the list of possible searchable fields and also access their contents.
Depending on your real requirements (you only showed a very abstract and specific version of them) one or the other method might be "the right one" for you. I would actually prefer the "everything into FieldPojo" as the most robust one, but on the other hand if you are not able to change FieldPojo and have to handle many different classes like it, the introspection variant might be the right one. (Be aware that it is fragile in terms of security and also probably very slow.)
Enums can contain method definitions, so one way is to define the method that retrieves the field name based on the enum value. I assume you have the actual field name stored as a member field also. Then you can override the method for the special ALL value:
enum SearchableFields {
ALL("all") { // all is just a placeholder in this case
#Override
String retrieveField(FieldPojo f) {
// logic for all fields
}
},
FIELD1("field1"),
FIELD2("field2"),
FIELD3("field3");
SearchableFields(String fieldName) {
this.fieldName = Optional.of(fieldName);
}
SearchableFields() {
fieldName = Optional.empty();
}
private final Optional<String> fieldName;
String retrieveField(FieldPojo f) {
if (fieldName.isPresent()) {
return (String) f.getClass().getField(fieldName.get()).get(f);
} else {
// ...
}
}
}
I am building Spring Boot webflux REST API functionality that needs to work with data containing few Java type's (let's consider String, Integer, Double for example) information as part of JSON request/responses. Attribute representing Java type must be persistable inside mongodb as well (should not be problem once JSON can work with such attribute). I have following model class and type enumeration which is used by REST API to serialize/deserialize JSON message's.
#Getter
#ToString
#EqualsAndHashCode(exclude = "id")
#Document(collection = "core_scheme")
#JsonDeserialize(builder = SchemeModel.Builder.class)
#Builder(builderClassName = "Builder", toBuilder = true, setterPrefix = "with")
public class SchemeModel {
#Id
private final String id;
#Field(name = "userId") private final String userId;
#Field(name = "date") private final String creationDate;
#Field(name = "properties") private final Map<String, SchemeTypes> properties;
}
public enum SchemeTypes {
INTEGER, STRING, DOUBLE
}
Serialization and deserialization work's well. Now the problem is that when i want to resolve real Java type's stored inside Map<String, SchemeTypes> properties map i need to do mapping similar to this (just abstraction not real code):
SchemeTypes.INTEGER => Java Integer class
SchemeTypes.STRING => Java String class
SchemeTypes.DOUBLE => Java Double class
Is there any more simple way to represent Java type's stored inside model class and used within serialized/deserialized JSON file's so i can directly use it to deduce Java type without additional validation that it's valid Java type. For example if type's enumarated inside mentioned enum would have exactly same naming as real Java type's i could do following without any mapping:
public void deduceClass(SchemeTypes type) {
Class myClass = Class.forName(type.toString());
}
Note that i am looking for a solution which would work out of the box (i don't have to validate type's provided by user). If such solution would be harder to implement as mentioned mapping i will stick with mapping.
If you weren't saving this entity I could say you can actually directly map the SchemeTypes into corresponding class like following
public enum SchemeTypes {
INTEGER(Integer.class), STRING(String.class), DOUBLE(Double.class);
private final Class clazz;
private SchemeTypes(Class clazz){
this.clazz = clazz;
}
public Class getClazz(){
return clazz;
}
}
But as you are saving this it could cause some issue to deserialize.
Maybe you can save not the SchemaType instance directly but just the name of enum to overcome this like following
private final Map<String, String> properties;
and find the corresponding clazz value with a static method on this class like following
public static Class findClazzFor(String schemeTypeName){
return SchemeTypes.valueOf(schemeTypeName).getClazz();
}
Nevertheless I think cleanest solution would be keeping the SchemeType class instance mapping somewhere as a one-to-one map. And retrieve the corresponding class for provided schemeType as in the getClazz method above.
I am having one class which is having getter and setter methods i am storing that getter method in mongodb with some other collection. After getting the method name from DB how to access that method. Whether it is possible to do like this or not?
public class MappingAlgorithmScoreGenerationRules {
#Field(value = FieldNames.CATEGORY)
private String category;
#Field(value = FieldNames.ATTRIBUTE_NAME)
private MappingScoreGenerationLogic attributeName;
#Field(value = FieldNames.PRIORITY)
private Integer priority;
#Field(value = FieldNames.ATTRIBUTE_SCORE)
private Integer attributeScore;
#Field(value = FieldNames.FINAL_THRESHOLD)
private Integer finalThreshold;
#Field(value = FieldNames.RESULT_COUNT)
private Integer resultCount;
#Field(value = FieldNames.NORMALIZED_VALUE)
private Integer normalizedValue;
#Field(value = FieldNames.GETTER_METHOD)
private String getterMethod;
}
This is the class where i am storing the method name.
public class MatchEntry {
private double matchedWeight;
public double getMatchedWeight() {
return matchedWeight;
}
public void setMatchedWeight(double matchedWeight) {
this.matchedWeight = matchedWeight;
}
}
getMatchedWeight is the method name i am going to store in the DB MappingAlgorithmScoreGenerationRules.
After getting the method name how to access the method name?
I want to access like
For example: MatchEntry.(the value get from db)
Use reflection API - https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
Method methodToInvoke
= MatchEntry.class.getMethod("methodName", methodParams,..);
methodToInvoke.invoke(matchEntryInstance, params,..);
In Java you can achieve method access by name using reflection (https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html).
This is a tutorial you may be able to use to lean more about this language feature: https://www.geeksforgeeks.org/reflection-in-java/
In your example, let's say you have loaded an instance of MappingAlgorithmScoreGenerationRules from the database, whose getterMethod attribute returns "getMatchedWeight".
Let's also assume that you have an instance of MatchEntry.
You would then access as follows:
MappingAlgorithmScoreGenerationRules rules = ....; //load from DB
MatchEntry entry = ...; //wherever it comes from
String getterMethodName = rules.getGetterMethod();
Method getter = MatchEntry.class.getMethod(getterMethodName);
Object value = getter.invoke(entry);
This code snippet omits Exceptions, in particular NoSuchMethodException and InvocationTargetException.
Please note that if you choose this approach, and depending heavily on the rest of your domain model, you will also need to be very careful with assumptions about the return type of the actual value (unless you can somehow guarantee that they are all the same, in which case you could cast the value).
Code that uses reflection is also inherently brittle and prone to failure as soon as you refactor. Imagine you have a populated database with these rules, and during a code review a couple of methods are renamed. Inoccuous change? Or will your entire setup break on the next deploy?
A (type-)safer approach might be to ensure all entries and related objects derive from an interface that standardises the return type on a getValue(String attributeName) method, so instead of messing with reflection you might do:
MappingAlgorithmScoreGenerationRules rules = ....; //load from DB
MatchEntry entry = ...; //wherever it comes from
String attributeName = rules.getAttribute(); //instead of 'getterMethod'
Object value = entry.getValue(attributeName);
where MatchEntry.getValue might be defined as:
public Object getValue(String attribute) {
switch(attribute) {
case "matchedWeight": return getMatchedWeight();
default: return null; //or you could throw an exception
}
}
This would easily survive any kind of method name refactoring and reorganisation, but adds the overhead of adding a case to the switch for every new attribute.
This problem could be partially solved with a runtime annotation that essentially binds an attribute name to a getter method, e.g.:
public class MatchEntry implements Matchable {
private double matchedWeight;
#MyCustomAnnotation("matchedWeight")
public double getMatchedWeight() {
return matchedWeight;
}
public void setMatchedWeight(double matchedWeight) {
this.matchedWeight = matchedWeight;
}
}
public interface Matchable {
default Object getValue(String attributeName) {
//read methods annotated with 'MyCustomAnnotation's in current class and call the one with matching value
}
}
Your getValue(String attributeName) would be tasked with reading these annotations and dynamically figuring out which getter to call. Still requires the annotation to be added everywhere it's needed, but at least it's with the getter and not hidden in some switch that's potentially duplicated across multiple class definitions.
Instead you just need a single default definition in the parent interface, as hinted above.
I'm calling a rest service that returns a json object. I'm trying to deserialize the responses to my Java Beans using Jackson and data-binding.
The example Json is something like this:
{
detail1: { property1:value1, property2:value2},
detail2: { property1:value1, property2:value2},
otherObject: {prop3:value1, prop4:[val1, val2, val3]}
}
Essentially, detail1 and detail2 are of the same structure, and thus can be represented by a single class type, whereas OtherObject is of another type.
Currently, I've set up my classes as follows (this is the structure I would prefer):
class ServiceResponse {
private Map<String, Detail> detailMap;
private OtherObject otherObject;
// getters and setters
}
class Detail {
private String property1;
private String property2;
// getters and setters
}
class OtherObject {
private String prop3;
private List<String> prop4;
// getters and setters
}
Then, just do:
String response = <call service and get json response>
ObjectMapper mapper = new ObjectMapper();
mapper.readValue(response, ServiceResponse.class)
The problem is I'm getting lost reading through the documentation about how to configure the mappings and annotations correctly to get the structure that I want. I'd like detail1, detail2 to create Detail classes, and otherObject to create an OtherObject class.
However, I also want the detail classes to be stored in a map, so that they can be easily distinguished and retrieved, and also the fact that the service in in the future will return detail3, detail4, etc. (i.e., the Map in ServiceResponse would look like
"{detail1:Detail object, detail2:Detail object, ...}).
How should these classes be annotated? Or, perhaps there's a better way to structure my classes to fit this JSON model? Appreciate any help.
Simply use #JsonAnySetter on a 2-args method in ServiceResponse, like so:
#JsonAnySetter
public void anySet(String key, Detail value) {
detailMap.put(key, value);
}
Mind you that you can only have one "property" with #JsonAnySetter as it's a fallback for unknown properties. Note that the javadocs of JsonAnySetter is incorrect, as it states that it should be applied to 1-arg methods; you can always open a minor bug in Jackson ;)
First of all I should probably say that the term 'constant object' is probably not quite right and might already mean something completely different from what I am thinking of, but it is the best term I can think of to describe what I am talking about.
So basically I am designing an application and I have come across something that seems like there is probably an existing design pattern for but I don't know what it is or what to search for, so I am going to describe what it is I am trying to do and I am looking for suggestions as to the best way to implement it.
Lets say you have a class:
public class MyClass {
private String name;
private String description;
private int value;
public MyClass(String name, String description, int value) {
this.name = name;
this.description = description;
this.value = value;
}
// And I guess some getters and setters here.
}
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
At first I thought that I should declare some static constants somewhere, e.g.
public static final String INSTANCE_1_DATA_FILE = "path/to/instance1/file";
public static final String INSTANCE_2_DATA_FILE = "path/to/instance2/file";
public static final String INSTANCE_3_DATA_FILE = "path/to/instance3/file";
public static final MyClass INSTANCE_1 = new MyClass(getNameFromFile(INSTANCE_1_DATA_FILE), getDescriptionFromFile(INSTANCE_1_DATA_FILE), getValueFromFile(INSTANCE_1_DATA_FILE));
public static final MyClass INSTANCE_2 = new MyClass(getNameFromFile(INSTANCE_2_DATA_FILE), getDescriptionFromFile(INSTANCE_2_DATA_FILE), getValueFromFile(INSTANCE_2_DATA_FILE));
public static final MyClass INSTANCE_3 = new MyClass(getNameFromFile(INSTANCE_3_DATA_FILE), getDescriptionFromFile(INSTANCE_3_DATA_FILE), getValueFromFile(INSTANCE_3_DATA_FILE));
Obvisouly now, whenever I want to use one of the 3 instances I can just refer directly to the constants.
But I started thinking that there might be a cleaner way to handle this and the next thing I thought about was doing something like:
public MyClassInstance1 extends MyClass {
private static final String FILE_NAME = "path/to/instance1/file";
public String getName() {
if (name == null) {
name = getNameFromFile(FILE_NAME);
}
return name;
}
// etc.
}
Now whenever I want to use the instances of MyClass I can just use the one I want e.g.
private MyClass myInstance = new MyClassInstance2();
Or probably even better would be to make them singletons and just do:
private MyClass myInstance = MyClassInstance3.getInstance();
But I can't help but think that this is also not the right way to handle this situation. Am I overthinking the problem? Should I just have a switch statement somewhere e.g.
public class MyClass {
public enum Instance { ONE, TWO, THREE }
public static String getName(Instance instance) {
switch(instance) {
case ONE:
return getNameFromFile(INSTANCE_1_DATA_FILE);
break;
case TWO:
etc.
}
}
}
Can anyone tell me the best way to implement this? Note that I have written the sample code in Java because that is my strongest language, but I will probably be implementing the application in C++, so at the moment I am more looking for language independent design patterns (or just for someone to tell me to go with one of the simple solutions I have already mentioned).
If you want the values to be constant, then you will not need setters, otherwise code can simply change the values in your constants, making them not very constant. In C++, you can just declare the instances const, although I'd still get rid of the setters, since someone could always cast away the const.
The pattern looks ok, although the fact that you are creating a new instance each time one is requested, is not usual for constants.
In java, you can create enums that are "smart" e.g.
public enum MyClass {
ONE(INSTANCE_1_DATA_FILE),
TWO(INSTANCE_2_DATA_FILE),
//etc...
private MyClass(String dataFile)
{
this(getNameFromDataFile(dataFile), other values...)
}
private MyClass(String name, String data, etc...)
{
this.name = name;
// etc..
}
public String getName()
{
return name;
}
}
In C++, you would create your MyClass, with a private constructor that takes the filename and whatever else it needs to initialize, and create static const members in MyClass for each instance, with the values assigned a new instance of MyClass created using the private constructor.
EDIT: But now I see the scenario I don't think this is a good idea having static values. If the types of ActivityLevel are fundamental to your application, then you can enumerate the different type of activity level as constants, e.g. a java or string enum, but they are just placeholders. The actual ActivityDescription instances should come from a data access layer or provider of some kind.
e.g.
enum ActivityLevel { LOW, MED, HIGH }
class ActivityDescription
{
String name;
String otherDetails;
String description; // etc..
// perhaps also
// ActivityLevel activityLevel;
// constructor and getters
// this is an immutable value object
}
interface ActivityDescriptionProvider
{
ActivityDescription getDescription(ActivityLevel activityLevel);
}
You can implement the provider using statics if you want, or an enum of ActivityDescription instnaces, or better still a Map of ActivityLevel to ActivityDescription that you load from a file, fetch from spring config etc. The main point is that using an interface to fetch the actual description for a given ActivityLevel decouples your application code from the mechanics of how those descriptions are produced in the system. It also makes it possible to mock the implementation of the interface when testing the UI. You can stress the UI with a mock implementation in ways that is not possible with a fixed static data set.
Now lets say that you know in advance that there will only ever be say 3 instances of this class, and the data is also known in advance (or at least will be read from a file at runtime, and the exact filename is known in advance). Basically what I am getting at is that the data is not going to be changed during runtime (once it has been set).
I'd use an enum. And then rather in this flavor:
public enum MyEnum {
ONE("path/to/instance1/file"),
TWO("path/to/instance2/file"),
THREE("path/to/instance3/file");
private String name;
private MyEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Which can be used as follows:
MyEnum one = MyEnum.ONE;
String name = one.getName();
(I'm too slow once again, you already accepted an answer, but here it is anyway...)
You want to (a) prevent changes to the data held in objects of MyClass, and (b) allow only a fixed set of MyClass objects to exist, implying that runtime code should not be able to create new instances of MyClass.
Your initial example has a public constructor, which violates (b)
I'd use a Factory approach so the Factory is the only thing that can create instances, and the class doesn't provide any setters so it's immutable.
Depending on how much flexibility you want for the future, you could put the factory and the class in the same package and limit scope that way, or you could make MyClass an inner class within the factory. You may also consider making MyClass an interface separate from its implementation.
A properties file could be used to configure the factory itself.
The properties file (e.g. "foo.properties") could look something like
one=/path/to/datafile1
two=/another/path/to/datafile2
three=/path/to/datafile3
I use "Foo" instead of "MyClass" in the (Java) examples below.
public class FooFactory
{
/** A place to hold the only existing instances of the class */
private final Map<String, Foo> instances = new HashMap<String, Foo>();
/** Creates a factory to manufacture Foo objects */
// I'm using 'configFile' as the name of a properties file,
// but this could use a Properties object, or a File object.
public FooFactory(String configfile)
{
Properties p = new Properties();
InputStream in = this.getClass().getResourceAsStream();
p.load(in); // ignoring the fact that IOExceptions can be thrown
// Create all the objects as specified in the factory properties
for (String key : p.keys())
{
String datafile = p.getProperty(key);
Foo obj = new Foo(datafile);
instances.put(key, obj);
}
}
public Foo getFoo(String which)
{
return instances.get(which);
}
/** The objects handed out by the factory - your "MyClass" */
public class Foo
{
private String name;
private String description;
private int value;
private Foo(String datafile)
{
// read the datafile to set name, description, and value
}
}
}
You're set to allow only your predefined instances, which can't be changed at runtime, but you can set it all up differently for another run at a later time.
Your first method seems to me like the best and the least prone to code rot. I'm not impressed by the idea of subclassing an object just to change the file name that contains the data that will be used to build it.
Of course, you could maybe improve on your original idea by wrapping these all in an outer class that provides some sort of enumeration access. A collection of MyClass's in other words. But I think you should discard this subclassing idea.
First, you really should be limiting where you use these instances in the code. Use them in as few places as possible. Given these are file names, I expect you want three class instances which accesses the files. How many classes are required depends on what your want to do with them? Look at the Singleton pattern for these classes.
Now you don't need the constants, but could have a helper class which will read the file containing the file names and supply them to the reader class. The code to find then name could also be a method called by the static initializer of the Singleton.
The common approach is to use a map:
private static final Map<String, YouClass> mapIt =
new HashMap<String, YouClass>(){{
put("one", new YourClass("/name", "desc", 1 )),
put("two", new YourClass("/name/two", "desc2", 2 )),
put("three", new YourClass("/name/three", "desc", 3 ))
}}
public static YourClass getInstance( String named ) {
return mapIt.get( named );
}
Next time you need it:
YouClass toUse = YourClass.getInstance("one");
Probably using strings as keys is not the best option but you get the idea.