Canonicalizing Java bean property names - java

I have a bunch of third-party Java classes that use different property names for what are essentially the same property:
public class Foo {
public String getReferenceID();
public void setReferenceID(String id);
public String getFilename();
public void setFilename(String fileName);
}
public class Bar {
public String getRefID();
public void setRefID(String id);
public String getFileName();
public void setFileName(String fileName);
}
I'd like to be able to address these in a canonicalized form, so that I can treat them polymorphically, and so that I can do stuff with Apache BeanUtils like:
PropertyUtils.copyProperties(object1,object2);
Clearly it would be trivial to write an Adapter for each class ...
public class CanonicalizedBar implements CanonicalizedBazBean {
public String getReferenceID() {
return this.delegate.getRefID();
}
// etc.
}
But I wonder is there something out there more generalized and dynamic? Something that would take a one-to-many map of property name equivalences, and a delegate class, and produce the Adapter?

I've never used it, but I think you're looking for Dozer:
Dozer is a Java Bean to Java Bean mapper that recursively copies data
from one object to another. Typically, these Java Beans will be of
different complex types.
Dozer supports simple property mapping, complex type mapping,
bi-directional mapping, implicit-explicit mapping, as well as
recursive mapping. This includes mapping collection attributes that
also need mapping at the element level.
Dozer not only supports mapping between attribute names, but also
automatically converting between types. Most conversion scenarios are
supported out of the box, but Dozer also allows you to specify custom
conversions via XML.

First Option is Dozer.
Second option is Smooks Framework
with a tweak. It will be beneficial to use Smook's Graphical mapper.
Another option would be XStream with custom Mapper.

maybe something like that:
public class CanonicalizedBar implements CanonicalizedBazBean {
public String getReferenceID() {
Method m = this.delegate.getClass().getDeclaredMethod("getReferenceID");
if(m == null)
m = this.delegate.getClass().getDeclaredMethod("getRefID");
...
return m.invoke();
}
// etc.
}

Although, I personally have never used it. I noticed that a project called orika is noted as having the best performance and the ability to automatically understand many such mappings.
At any rate it also supports custom mappings and uses generated code to implicitly define the adapters.
You can also define a custom mapper, that is if you know how to canonize the member names you can use that knowledge to build a mapping that is true for all your objects. for instance:
DefaultFieldMapper myDefaultMapper = new DefaultFieldMapper() {
public String suggestMapping(String propertyName, Type<?> fromPropertyType) {
// split word according to camel case (apache commons lang)
String[] words= StringUtils.splitByCharacterTypeCamelCase(propertyName);
if(words[0].length() > 6) {
// trim first camel-cased word of propery name to 3 letters
words[0]= words[0].substring(0,2);
return StringUtils.join(words);
} else {
// remains unchanged
return propertyName;
}
}
}
mapperFactory.registerDefaultFieldMapper(myDefaultMapper );

I haven't done much with it but you may be able to use Aspect Oriented Programming to do this.
What you should be able to do I think is add a method to each of the classes that internally calls the real method. See this article about half way down it talks about mixins.
AspectJ is probably the most popular implementation.

Related

How to dynamically generate a Java Bean class using plain Java?

I went through some of the samples that have used libraries to generate bean classes from JSON, XML etc. What I would like to know is, whether there's a way to dynamically generate a java bean class, with the parameters I give?
For example if I give an array of Strings as arguments which would represent the properties of the Pojo class for now, how can I generate the POJO?
Arguments: {"field1", "field2", "field3"}
Generate POJO would be:
public class TestBean {
private String field1;
TestBean() {
}
public String getField1() {
return field1;
}
public void setField1(String field1) {
this.field1 = field1;
}
}
It should be the same for field2 and field3 as well.
Here I'm assuming that all the properties above are String and the class name is constant for now. Is there any way I can achieve this? Thanks in advance.
The problem with generating an actual Java class at runtime is that there is no way you can access it using standard Java syntax as the compiler doesn't know about it.
In practice therefore, most people just use a map in this circumstance. The only case I can think where you would need to generate a real class is where there is some other code you can't change that requires a Java object and inspects it dynamically using reflection or otherwise.
If you don't need this you are better off using a map, or possibly some utility class designed to emulate a Java Bean.
The Apache BeanUtils package provides the DynaBean interface to implement dynamic Java Beans. That said, the classes are only recognised as beans if accessed from the rest of the BeanUtils package.
There are several subclasses depending on what you want, for example, LazyDynaBean:
DynaBean myBean = new LazyDynaBean();
myBean.set("myProperty", "myValue");

Map a collection with parameter with mapstruct

To map a certain object with mapstruct I need some custom post processing which needs an additional parameter to do it's work:
#Mapper
public abstract class AlertConfigActionMapper {
#Mappings({ #Mapping(target = "label", ignore = true)})
public abstract AlertConfigActionTO map (AlertConfigAction action, Locale userLanguage);
#AfterMapping
public void setLabel (AlertConfigAction action, #MappingTarget AlertConfigActionTO to, Locale userLanguage) {
for (AlertConfigActionLabel label : action.getAlertConfigActionLabels()) {
if (label.getLanguage().equals(userLanguage)) {
to.setLabel(label.getLabel());
break;
} else if (label.getLanguage().equals(Locale.ENGLISH)) {
to.setLabel(label.getLabel());
}
}
}
}
This works just fine.
The problem starts when I add following method to this mapper:
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, Locale userLanguage);
I need to pass this parameter (userLanguage) as well but mapstruct seems to 'break down' in this case: I generates following code for this part (which naturally gives a compilation error):
#Override
public List<AlertConfigActionTO> mapList(List<AlertConfigAction> actions, Locale userLanguage) {
if ( actions == null && userLanguage == null ) {
return null;
}
List<AlertConfigActionTO> list = new List<AlertConfigActionTO>();
return list;
}
I'm sure it is related to the parameter since if I remove it (from all mapping methods) then the mapList method is generated correctly.
What is needed to be done to allow custom parameters in this case?
What you describe is not possible (yet). Could you open a feature request in our issue tracker? We should provide means of denoting parameters as some sort of "context" which is passed down the call stack.
As a work-around for the time being, you might take a look at using a ThreadLocal which you set before invoking the mapping routine and which you access in your after-mapping customization. It's not elegant - and you need to make sure to clean up the thread local to avoid memory leaks - but it should do the trick.
I know that this question is quiet old, but I run into this issue, and starting at version 1.2 of mapstruct you can resolve it using #Context
So declaring the mapping for the list need to be like this :
public abstract ArrayList<AlertConfigActionTO> mapList (List<AlertConfigAction> actions, #Context Locale userLanguage);
Now, you juste need to add another non abstract mapping like this :
public AlertConfigActionTO mapConcrete (AlertConfigAction action, #Context Locale userLanguage){
return map (action, userLanguage);
}
I don't think it is possible. At least not that way. Problem is that you prepare interface/abstract class - and rest is done by the engine. And that engine expects methods with one parameter... There are decorators, but they go the same way. I would try to inject language. Create bean, mark it as session scoped, and find out. With Spring, you would use ScopedProxyMode for that... Not sure how that goes with CDI.
Other option is more workaround, then solution - maybe that AlertConfigAction can pass that information?

What is the alternative to static in java interface

I have a design question.
I have an interface that read XML. Each implementer class read different XML and I want a way to identify which implementer should I dynamically create for the xml type I get.
The problem is that java interface can't have static members. What is the best way to do it?
Example:
public interface MyXML{
public void readXML(String xml);
public final static String getType();
}
Usage:
func(String xml, String type)
{
MyXML obj;
switch(type)
{
case MyImpl.getType():
obj = new MyImpl();
break;
case MyImpl2.getType():
obj = new MyImpl2();
break;
}
obj.readXML(xml);
}
EDIT:
I'll try to explain better what I want:
I need to know which xml can be read by which implementation and I search for a way to force anyone that implements MyXML to tell which xml it can read so I'll not need to maintain the translation outside in another list or factory.
Java only allow static constants in the interface. In Java 8 you can have also default implementations, but that's a different thing.
One way to solve this is to make getType normal instance method, same as readXML and instantiate implementations in advance, something like this
// somewhere in the constructor or main
List<MyXML> readers = Arrays.asList(new MyImpl1(), new MyImpl2());
public MyXML findReaderForType(String type) {
for (MyXML reader : readers) {
if (reader.getType().equals(type)) {
return reader;
}
}
}
However you need to be careful to design your implementations in the way, so they can be reused.
Another option is to create some sort of static factory, which will contain the equivalent of findReaderForType method. Then the mapping between the type and implementation is contained in this factory class.
Take a look at Factory Design Pattern. The client should call the factory passing the Type, then the factory returns an instance of the correct class:
public class MyFactory {
public MyXML createMyXML(Type type) {
return ...
}
}
This way the client is free from the responsability to know which concrete class needs to be provided.
There's no point in storing implementation types in interface. The interface shouldn't know about implementations. Instead you can store the XML Type in Enum.
enum Type{
TYPE1,
TYPE2;
}
Then you can create a Map<Type, MyXML> variable and add implementations with their corresponding Type in it.
Factory can then be something like:
public MyXml getImplementation(String type){
Type type = Type.valueOf(type);
MyXml impl= implementations.get(type);
if(impl == null){
throw new UnsupportedOperationException();//or whatever ex you see fit
}
return impl;
}
I suggest you design your system around instances, not types themselves.
The application would instantiate all the XML reader types and would query each instance for the type it is in charge of. You can use that to organize the XML readers into a map and retrieve them with no switch or if-statements.
If there are some heavyweight resources associated with an instance in your current design, then change that design such that all the resource acquisition happens later into the object's lifecycle, not at construction time.
If you need several instances of the same reader at once (for example, in a concurrent setting), then use the idea exemplified by java.util.regex.Pattern and its corresponding Matcher. A pattern is a thread-safe factory of single-threaded, disposable matchers.

Force the usage of a JPA AttributeConverter for enums

We're trying to figure out a robust way of persisting enums using JPA. The common approach of using #Enumerated is not desirable, because it's too easy to break the mappings when refactoring. Each enum should have a separate database value that can be different than the enum name/order, so that you can safely change the name or internal ordering (e.g. the ordinal values) of the enum without breaking anything. E.g. this blog post has an example on how to achieve this, but we feel the suggested solution adds too much clutter to the code. We'd like to achieve a similar result by using the new AttributeConverter mechanism introduced in JPA 2.1. We have an interface that each enum should implement that defines a method for getting the value that is used to store the enum in the database. Example:
public interface PersistableEnum {
String getDatabaseValue();
}
...
public enum SomeEnum implements PersistableEnum {
FOO("foo"), BAR("bar");
private String databaseValue;
private SomeEnum(String databaseValue) {
this.databaseValue = databaseValue;
}
public void getDatabaseValue() {
return databaseValue;
}
}
We also have a base converter that has the logic for converting enums to Strings and vice versa, and separate concrete converter classes for each enum type (AFAIK, a fully generic enum converter is not possible to implement, this is also noted in this SO answer). The concrete converters then simply call the base class that does the conversion, like this:
public abstract class EnumConverter<E extends PersistableEnum> {
protected String toDatabaseValue(E value) {
// Do the conversion...
}
protected E toEntityAttribute(Class<E> enumClass, String value) {
// Do the conversion...
}
}
...
#Converter(autoApply = true)
public class SomeEnumConverter extends EnumConverter<SomeEnum>
implements AttributeConverter<SomeEnum, String> {
public String convertToDatabaseColumn(SomeEnum attribute) {
return toDatabaseValue(attribute);
}
public SomeEnum convertToEntityAttribute(String dbData) {
return toEntityAttribute(SomeEnum.class, dbData);
}
}
However, while this approach works very nicely in a technical sense, there's still a pretty nasty pitfall: Whenever someone creates a new enum class whose values need to be stored to the database, that person also needs to remember to make the new enum implement the PersistableEnum interface and write a converter class for it. Without this, the enum will get persisted without a problem, but the conversion will default to using #Enumerated(EnumType.ORDINAL), which is exactly what we want to avoid. How could we prevent this? Is there a way to make JPA (in our case, Hibernate) NOT default to any mapping, but e.g. throw an exception if no #Enumerated is defined on a field and no converter can be found for the type? Or could we create a "catch all" converter that is called for all enums that don't have their own specific converter class and always throw an exception from there? Or do we just have to suck it up and try to remember the additional steps each time?
You want to ensure that all Enums are instances of PersistableEnum.
You need to set a Default Entity Listener (an entity listener whose callbacks apply to all entities in the persistence unit).
In the Default Entity Listener class implement the #PrePersist method and make sure all the Enums are instances of PersistableEnum.

how to read object attribute dynamically in java?

Is there any way to read and print the object attribute dynamically(Java) ? for example if I have following object
public class A{
int age ;
String name;
float income;
}
public class B{
int age;
String name;
}
public class mainA{
A obj1 = new A();
method(A);
method(B);
}
the output should be like
While running method(A):
Attribute of Object are age,name,income;
While executing method(B):
Attribute of Objects are age,name;
My question is I can pass various object in method(), is there any way I can access the attribute of the differnt object in general.
You want to use The Reflection API. Specifically, take a look at discovering class members.
You could do something like the following:
public void showFields(Object o) {
Class<?> clazz = o.getClass();
for(Field field : clazz.getDeclaredFields()) {
//you can also use .toGenericString() instead of .getName(). This will
//give you the type information as well.
System.out.println(field.getName());
}
}
I just wanted to add a cautionary note that you normally don't need to do anything like this and for most things you probably shouldn't. Reflection can make the code hard to maintain and read. Of course there are specific cases when you would want to use Reflection, but those relatively rare.
Using org.apache.commons.beanutils.PropertyUtils we can do this. If the proper getters and setters are defined for the bean we can also dynamically set the value:
import org.apache.commons.beanutils.PropertyUtils;
import java.beans.PropertyDescriptor;
public class PropertyDescriptorTest {
public static void main(String[] args) {
// Declaring and setting values on the object
AnyObject anObject = new AnyObject();
anObject.setIntProperty(1);
anObject.setLongProperty(234L);
anObject.setStrProperty("string value");
// Getting the PropertyDescriptors for the object
PropertyDescriptor[] objDescriptors = PropertyUtils.getPropertyDescriptors(anObject);
// Iterating through each of the PropertyDescriptors
for (PropertyDescriptor objDescriptor : objDescriptors) {
try {
String propertyName = objDescriptor.getName();
Object propType = PropertyUtils.getPropertyType(anObject, propertyName);
Object propValue = PropertyUtils.getProperty(anObject, propertyName);
// Printing the details
System.out.println("Property="+propertyName+", Type="+propType+", Value="+propValue);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
To set the value of a particular property:
// Here we have to make sure the value is
// of the same type as propertyName
PropertyUtils.setProperty(anObject, propertyName, value);
Output will be:
Property=class, Type=class java.lang.Class, Value=class genericTester.AnyObject
Property=intProperty, Type=int, Value=1
Property=longProperty, Type=class java.lang.Long, Value=234
Property=strProperty, Type=class java.lang.String, Value=string value
You can use reflection to get every field from your object (if security configuration allows you).
If you need it not for the sake of self-education, then it may be worth using ReflectionUtils from Apache Commons.
You can use reflection, but the API is not very nice to use. But what you are trying to do is not at all object-oriented. The A and B should have method "print yourself" which would output their values (you should specify the method in superclass/interface to call the method using polymorphism).
I think I would consider a different approach.
If you really want to treat these like data is there any reason they couldn't be hashtables (Do they have associated code)?
Reflection will do it but it's a last resort--you should always seriously consider different approaches before dropping to reflection.
Cases where you must access variables like that exist--like database mapping (Hibernate) and injection (Spring). You might want to consider if a packaged solution like that fits your need so that future programmers can understand what you did without learning everything about your specific solution.
Also, Spring injection can do things that might fit your needs.
Also also if you are going to use reflection, seriously consider annotations so that you aren't tying your functionality to what should be simple arbitrary attribute names.

Categories

Resources