I have this question. But it will be difficult for me to explain as I don't know exact terms to use. Hope someone will understand. I'll try to discribe to the best i can. I feel like this is much related to parsing
Say there are two classes. And in both classes I have some variables, say strings (just for simplicity, variable type can be any), which have similar names.
Eg:
class ClassA{
String x,y,z;
}
class ClassB{
String x,y,z;
}
Now, what i need is, i need to copy the value of one class's variable values to other classes corresponding variable.
Eg:
ClassA aa=new ClassA();
ClassB bb=new ClassB();
//set bb's variables
aa.x=bb.x;
aa.y=bb.y;
aa.z=bb.z;
like that.
But please note that what i need is not the above method. I hope there will be a way to write a simple method, so that it will identify the relevent variable by the name passed to it. Then it will do the value assignment accordingly.
My imagined method is like this,
void assign(String val){
// aa.<val>=val
}
For example if you pass bb.x to assign(...) method, then it will do aa.x=bb.x assignment.
Hope this is clear enough. There must be a better way to explain this. If someone know it please edit the post(+title) to make it more clear (But save my idea)..
Please let me know if there's a way to achieve this.
Thanks!
Dozer is fine, see Jean-Remy's answer.
Also, if the variables have getters and setters according to the JavaBeans standard, there are a number of technologies that could help you, e.g. Apache Commons / BeanUtils
Sample code (not tested):
final Map<String, Object> aProps = BeanUtils.describe(a);
final Map<String, Object> bProps = BeanUtils.describe(b);
aProps.keySet().retainAll(bProps.keySet());
for (Entry<String, Object> entry : aProps.entrySet()) {
BeanUtils.setProperty(b,entry.getKey(), entry.getValue());
}
Update:
If you don't have getters and setters, here's a quick hack that copies field values from one class to another as long as the fields have common names and types. I haven't tested it, but it should be OK as a starting point:
public final class Copier {
public static void copy(final Object from, final Object to) {
Map<String, Field> fromFields = analyze(from);
Map<String, Field> toFields = analyze(to);
fromFields.keySet().retainAll(toFields.keySet());
for (Entry<String, Field> fromFieldEntry : fromFields.entrySet()) {
final String name = fromFieldEntry.getKey();
final Field sourceField = fromFieldEntry.getValue();
final Field targetField = toFields.get(name);
if (targetField.getType().isAssignableFrom(sourceField.getType())) {
sourceField.setAccessible(true);
if (Modifier.isFinal(targetField.getModifiers())) continue;
targetField.setAccessible(true);
try {
targetField.set(to, sourceField.get(from));
} catch (IllegalAccessException e) {
throw new IllegalStateException("Can't access field!");
}
}
}
}
private static Map<String, Field> analyze(Object object) {
if (object == null) throw new NullPointerException();
Map<String, Field> map = new TreeMap<String, Field>();
Class<?> current = object.getClass();
while (current != Object.class) {
for (Field field : current.getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers())) {
if (!map.containsKey(field.getName())) {
map.put(field.getName(), field);
}
}
}
current = current.getSuperclass();
}
return map;
}
}
Call Syntax:
Copier.copy(sourceObject, targetObject);
Did you ever heared about Dozer ? : http://dozer.sourceforge.net/
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 allow you to map Java Beans :
using their names (implicit mapping), i.e mapping ClassA.x to ClassB.x
providing hability to map diffrent structures (explicit mapping) with different names with (quite simple) xml or annoation configuration .
Here a XML example on the library site :
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">
<mapping>
<class-a>org.dozer.vo.TestObject</class-a>
<class-b>org.dozer.vo.TestObjectPrime</class-b>
<field>
<a>one</a>
<b>onePrime</b>
</field>
</mapping>
<!-- SNIP ... -->
</mappings>
This will map object org.dozer.vo.TestObject into TestObjectPrime, mapping all variable that are identicals together (like in your case) and variables TestObjectFoo.oneFoo into TestObjectFooPrime.oneFooPrime.
Great, isn't it ?
Look here. Just use BeanUtils.copyProperties(newObject, oldObject);
new answer.
I'd suggest looking into Dover as it seems pretty straightforward.
The second option is serializing classes into XML and deserializing into your target class only on members that match.
The third option I mentioned in the comment was using reflection - http://java.sun.com/developer/technicalArticles/ALT/Reflection/
This technique allows for a nice design pattern called Introspection - Java introspection and reflection which in turn allows you to discover members of a certain class...
Now, having said that, one would simply "discover" members of ClassA, fill a ArrayList with their names, discover members of ClassB, fill another ArrayList with their names, and copy values of the intersecting set. At least that's my idea on it.
Related
I have got a Class PagedResult. The class is there to help me realize a JSON output with different objects in a pages format. The E is the object, that is wrapped in the List. It works all fine, but one thing still bothers me. I would like that the list with the objects does not always get the same name. I would like to adapt the name to the corresponding objects.
Class PagedResult:
public class PagedResult<E> {
Long totalItems;
Integer totalPages;
Integer currentPage;
List<E> elements;
[... Getter & Setter ...]
}
The actual JSON Output with an Object like MyPojo looks like this:
{
"totalItems": 2,
"totalPages": 1,
"currentPage": 1,
"elements": [
{
"myPojoAttr1": "hello",
"myPojoAttr2": "there"
},
{
"myPojoAttr1": "hello",
"myPojoAttr2": "folks"
}
]
}
So for each response, no matter which objects, the array is namend as "elements". I don´t want the ugly name in my JSON response, because of the changing objects in the PagedResult-class. When I get a response with objects like MyPojo the name of the JSON-Array should be "myPojos" and when I want to get a response with objects like MyWin the name "myWins".
I tried alot with #JsonProperty, but I can´t find a way, to do this "object-array-name" also generic. Can someone assist me with the problem please? Thanks in advance.
No. You can't do that. Generic types have parameters for types, not for identifiers. AFAIK, nothing in the Java language allows you to treat a Java identifier as a parameter when producing a type. (Certainly, nothing you could use in this context!)
Alternatives:
Don't do it. (Take a good hard look at your reasons for wanting the JSON attribute name to vary. What does it actually achieve? Is it worth the effort?)
Don't use a generic type. Define a different class for each kind of "paged result". (Clunky. Not recommended.)
Use a map, and populate it with a different map key for the elements attribute of each kind of "paged result". (The disadvantage is that you lose static type checking, and take a small performance and storage penalty. But these are unlikely to be significant.)
Write a custom mapper to serialize and deserialize the PagedResult as per your requirements.
For what it is worth, identifiers as parameters is the kind of thing you could do with a macro pre-processor. That Java language doesn't have standard support for that kind of thing.
Yes it's possible, using custom serializers. But even with a custom serializer you still have a problem: Generics are removed at compile time. So we need to somehow get the type during runtime.
Here is an example that will just check the type of the first element in the elements list. Definietly not the cleanest way to do it, but you don't have to adjust your PagedResult class.
public class PagedResultSerializer<T> extends JsonSerializer<PagedResult<Object>> {
#Override
public void serialize(PagedResult<Object> value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeNumberField("totalItems", value.getTotalItems());
// Your other attributes
if (!value.getElements().isEmpty()) {
Object firstElement = value.getElements().get(0);
String elementsFieldName;
if (firstElement instanceof MyPojo) {
elementsFieldName = "myPojos";
} else if (firstElement instanceof MyWin) {
elementsFieldName = "myWins";
} else {
throw new IllegalArumentException("Unknown type");
}
serializers.defaultSerializeField(elementsFieldName, value.getElements(), gen);
}
gen.writeEndObject();
}
}
Now you just need to tell Jackson to use this serializer instead of the default one.
#JsonSerialize(using = PagedResultSerializer.class)
public class PagedResult<T> {
// Your code
}
Improvments: Add a Class<T> elementsType attribute to your PagedResult and use this attribute in your serializer instead of checking the first element in the list.
Another approach: use inheritance.
Have an abstract base class PagedResult that contains all the common fields, to then distinctively subclass it to PagedResultWithElements, PagedResultWithMyPojo and so on. And the subclasses contain just that "type" specific list.
As a drawback: you get some code duplication. But on the other side, you get quite more control over what happens without doing overly complicated (de)serialization based on custom code.
So, when you know the different flavors of "element types", and we talk say 3, max 5 different classes, using inheritance might be a viable solution.
We have some data in properties file. This data is used across many classes. So, we create a Properties class object in each and every class and then read data using getProperty() method. This is leading to duplication of code.
Can someone please suggest some best practices to avoid this?
One thing that came to my mind is:
Create a class
Have a public variable for each property in property file in this class
Have a method that assigns values to each and every property
In the class where property values are required, create an object for this class and access the public variables
But, things i don't like with this approach are public variables and if at all a new property is added to the property file, i need to add code to read that property in the class.
Any help is appreciated.
Thank you!
You can create a Singleton class, that loads the properties the first time it gets invoked.. and a public method that retrieves the property value, for a given property key..
This is assuming you're using a standart Properties file... But you can extrapolate this to any key-value pair, changing Properties type to a Map or something else.
Something like
public class PropertyHandler{
private static PropertyHandler instance = null;
private Properties props = null;
private PropertyHandler(){
// Here you could read the file into props object
this.props = .....
}
public static synchronized PropertyHandler getInstance(){
if (instance == null)
instance = new PropertyHandler();
return instance;
}
public String getValue(String propKey){
return this.props.getProperty(propKey);
}
}
Then you can invoke this as needed.. from any code.. like this.
String myValue = PropertyHandler.getInstance().getValue(propKey);
Hope this helps
for me static inner class is the best possible way to do it. It will do it with lazily, as class loading is synchronized so thread safe, plus performant also. So with this we are achieving three things:
good performance because with synchronizing the liveliness will suffer, but here we are using static inner class.
thread safety because when inner class will be loaded than only map will be initialized as the class loading is thread safe hence all total thread safe.
Inner class will be loaded when we will call Singleton.initialize().get(key) so the map gets initialized lazily.
Below is the code...
public class SingletonFactory
{
private static class Singleton
{
private static final Map<String, String> map = new HashMap<String, String>();
static
{
try
{
//here we can read properties files
map.put("KEY", "VALUE");
}
catch(Exception e)
{
//we can do the exception handling
System.out.println(e);
}
}
private static Map<String, String> initialize()
{
return map;
}
}
public static String getValue(String key)
{
return Singleton.initialize().get(key);
}
}
One out of the box option is to use system properties. You can add your own system properties to your execution environment.
You can do this with a dedicated class having a static Properties object. See here for an example.
I could be misunderstanding your data flow here, but this is what seems "normal" to me:
Create a readPropFile method.
This should read a file and appropriately parse the properties it finds.
These properties can be stored in a Map<String, Object>, hashed by property name.
Read property file once (presumably when the application starts, or whenever it's appropriate to load properties) --> Properties object (say, props).
Pass props around to anything that needs access to those properties.
Or if you don't want to pass it around explicitly, use a static accessor as illustrated here.
Access properties using props.get("PROPERTY_NAME") (which just looks up that property in the internal Map).
If you don't want to use String lookups, you can keep an enum of valid property names somewhere, and do storage/lookups using that, but then you have to update that enum every time you add a new property to the file.
I've had success using an Enum, and in the constructor using the name() method to read a property of the same name. Be sure to handle exceptions in a reasonable way or else the whole class will fail to load and you won't get a helpful error message.
Benefits of this approach are that each enum value automatically corresponds to a property without having to write individual mapping code for each property. You do of course need an enum value for each property (that's unavoidable if you want DRY prop references), but you avoid repetitive per-property initialization code using unchecked Strings.
Drawbacks are that enums don't allow generic types, so if you wanted certain properties to return Integer and others to return String, then you might be better served with a classic singleton class design.
If you want to go crazy with this you could also write a script to generate your Enum or singleton java source code from the properties file, to keep your code extra DRY.
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.
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.
In java i have a bean object(type unknown) i want to put the values of members of that bean into one HashMap with class members as key.Without using reflection can i do that if so how ? otherwise tell me a good way to do it using reflection
beanObject = { name="raja",age="20"} to haspMapObj = {name="raja",age="20"}
As peoples you said i tried introspector:
thank you for your answer and advise friends.
Class myClass =myObj.getClass();
info = Introspector.getBeanInfo(myClass);
for ( PropertyDescriptor pd : info.getPropertyDescriptors() ){
String name = pd.getName();
System.out.println("*************"+name+","+ pd.getValue(name));
}
but the above is print only the name the value's is coming as null. bcoz we are passing only the class type not the object reference. how do we do to get the value?
You can use the Introspector to get all the fields of a bean and their values. (This wraps reflection)
I think you can't do it without reflection. With reflection you can do something like this:
Map<String, Field> map = new HashMap<String, Field>();
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
map.put(field.getName(), field);
}
I do not see any possibility without using reflection at least indirectly via frameworks.
If you take a look at the Apache Commons Beanutils you might find some helpful methods:
http://commons.apache.org/beanutils/
More specified:
http://commons.apache.org/beanutils/v1.8.3/apidocs/org/apache/commons/beanutils/BeanMap.html
Best regards!
You can use introspection, which is based on reflection:
http://download.oracle.com/javase/6/docs/api/java/beans/Introspector.html
But what exactly do want to do in the end? Maybe there is a better way...
To get the value from a PropertyDescriptor pd:
Object value = pd.getReadMethod().invoke(myObj, new Object[]{});
Note, some time ago I wrote a utility class, which you might find useful:
http://softsmithy.sourceforge.net/lib/docs/api/org/softsmithy/lib/beans/BeanIntrospector.html