How to log internals of an arbitrary object in Java? - java

I have a Java object with some unknown structure. Now I want to output this structure (properties and their values) to log file. And of course I'm interested to do this in recursive mode. Are there any libraries that can help me?

XStream is extremely good at printing object graphs, even handling cycles without any extra configuration or extra code in your classes (i.e. no messing with toString()'s). Just add the library and you can do this to anything and get nice, useful output:
log.debug("The object: {}", new XStream().toXML(anyObject));
That will give you XML output. If you prefer JSON, you can get it with a tiny bit more work as detailed in the XStream JSON tutorial.

I suggest you look either at Apache Commons BeanUtils or Apache Commons Lang, specifically ReflectionToStringBuilder.

Java serialization, which comes with Java, should do the trick. It will be in binary format though.
There is also XML serialization which can be provided by JAXB

you could use reflection
getClass and then go over each instance variable and go on (some objects can be handled specifically (like Strings))

You should use reflection. Have a look at java.lang.Class class, specifically .getFields() method.

I have found the Apache Commons ToStringBuilder.reflectionToString() very useful. To get recursion you can override each Object's toString() method with a call to this function passing this.
http://commons.apache.org/lang/api-2.6/org/apache/commons/lang/builder/ToStringBuilder.html

The java reflection API will give you access to all of this stuff (private members and all). To get private members, you will need to get yourObject.getClass().getDeclaredFields() to access a private field, remember to call yourField.setAccesible(true) on it.
Of course, you are very quickly going to run into problems by handrolling your own class to do this via reflection. The main problems come in when trying to decide to finally print a value and determining if it is an enum, a primitive, a primitive array and so on. You can use the Class.isPrimitive method to help figure that step out. To access elements of an array, use the java.lang.reflect.Array class.
The best option, which was posted earlier, is to use the ReflectionToStringBuilder of apache commons.

A json serializer will do the job, e.g. using Gson:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
...
private static final Logger LOG = LoggerFactory.getLogger(Your.class);
...
Object obj = ...;
LOG.info(new Gson().toJson(obj));

Related

Alternatives to Reflection

I would like to implement my own Universal Binary JSON Specification-like specification. As one of my first steps I would like to have a method, which takes an object as parameter, like Gson does in its String com.google.gson.Gson.toJson(Object src) method. So I would like to know the fields and the data types of them. As far as I know does Gson use reflection to achieve that.
Another "solution" could be Serialization. But it's maybe tough to extract the fields from there, and I would prefer anyway, that it's not a must for the object to implement Serializable.
Is Reflection the way to go with my intentions?
You may consider bean introspection (see java.beans.Introspector) for a cleaner, albeit more limited approach.
If your objects are not pure beans (i.e. you need to map fields without getters or setters), you need to use reflection.

Java: Static string localization

Are there any tool that will compile a java .properties file to a class which I can use in Java EE (tomcat) application? Similar to android where the eclipse plugin produces a static R.strings class.
I found this article:
http://www.techhui.com/profiles/blogs/localization-in-gwt-using
But it is dependant on GWT. Any help appreciated.
I have never heard about such tool. GWT has a great deferred-binding based technique but it is not the thing you are looking for. However I think it is possible to implement a basic code generator for such tasks.
But the answer to your question is: as far as I know there isn't.
To internationalize applications I implemented a Message Compiler, which creates the resource bundle files and constant definitions as Java enums or static final strings for the keys from one single source file. So the constants can be used in the Java source code, which is a much safer way than to use plain strings. In this case you also get a compile time error, when you use a key constant, that doesn't exist. The message compiler cannot only be used for Java. It creates also resource files and constants for Objective-C or Swift and can be extended for other programming environments.
What about ResourceBundle?
// refers to "src/config.properties"
ResourceBundle config = ResourceBundle.getBundle("config");
String property1 = config.getString("property1");
I think one could write a very simple grammar for properties files using ANTLR in a custom a maven plugin (or Ant task) that just generates the Java source before the compilation step.
How about storing your properties in a JSON file. The JSON object stored in the file should map to a Java class, use Jackson mapper to deserialize. With Jackson you can enforce that all fields must be non-null on deserialize.
You can also use GSON and write a custom deserializer that performs checks as strict as you want them. Example - you can enforce not null along with not empty for strings.
Compiler Assisted Localization (CAL10N) is not exactly what you asked, but may be of help.
Although it does not generate Java classes from .properties, using enums as message keys is still better than strings, as you get some help from the compiler.
Declare a enum, bind it to .properties with annotation and use enum values in message lookups. I have not tried it yet, though. See manual.

Java/Ruby: is there a way to do .constantize or Object.send() in Java?

In Ruby, you can do "var1".constantize to get the actual variable var1.
Ruby also has Model.Send("method name, parameters can be here, etc"), and it would be the same as actually calling that method.
What I want to do.. is... kinda tricky... I want the string "var1 == var2" to be converted to actual variables in my java app, then evaluated.
Is there a way to do this?
Have you considered using JRuby?
As to your questions:
There is no peer to constantize that will allow for an eval like syntax where you can pass in a String and convert it to code in Java. You can do things like Class.forName to load a particular class from a String, but it doesn't sound that is what you are looking for.
You can use the Java reflection API to dynamically invoke methods on a class Check out Jakarta Commons BeanUtils for some utility methods that may help.
In Java, similar behaviour is achieved through the Reflection API. However, since Java is a compiled language, local variables' (within methods, constructors, parameters, etc) information is erased on compilation.
However you still have complete access to class names, hierarchies, methods and fields (class variables).
A good starting point is the Reflection API tutorial or the getClass() method of Object.
In Java if you want a dynamic lookup of variables, you would typically place them in a Map and lookup use the keys of that Map.
Can you explain what you are trying to do in more detail, I suspect what you are trying to do can be done simply a different way in Java.

How can I have more flexible serialization and deserialization in Java?

If I serialize an object in Java, and then later add an extra field to the java class, I can't deserialize the object into the modified class.
Is there a serialization library or some way that I can have deserialization be less strict, like if there is an extra field added to the class then it just fills that with null upon deserialization of the old version of the class?
You need to keep a serialVersionUID on your class. Check out the section "Version Control" in this article by Sun.
You've got lots of potential options.
You could use a graph serialisation library to define and manage your format e.g. Google's protocol buffers or Kryo. I believe both of these have built-in support for versioning.
You can write your own custom serialisation code and handle the versions explicitly - e.g. serializing to a flexible format like XML. When reading the XML you can configure it to use default values if a particular field isn't specified.
Or you could design your class in a "flexible" way, e.g. have all the fields stored in a HashMap and indexed by Strings. Depending on what you are trying to do, this may be a convenient option.
There's a fair few serialization libraries, take a look at Simple though:
http://simple.sourceforge.net/
or as mentioned above Google Protocol Buffers.
http://code.google.com/apis/protocolbuffers/
Implement Externalizable and you can do whatever you want. The puts the onus of serial/deserialization completely upon the class being serialized.
Did you add a serialVersionUID? This must be present (and unchanged) if you want to serialize / deserialize different Versions of a class.
Furthermore you can add the following two methods to your class to define exactly the serialization process:
private void writeObject(java.io.ObjectOutputStream stream)
throws IOException;
private void readObject(java.io.ObjectInputStream stream)
throws IOException, ClassNotFoundException;
The Javadoc of ObjectInputStream gives more detail on its usage.
If I serialize an object in Java, and
then later add an extra field to the
java class, I can't deserialize the
object into the modified class.
That's untrue for a start. You need to have a good look at the Versioning section of the Object Serialization specification before you go any further.

Is there a java reflection API around the java.lang.reflect package?

A lot of Java projects use reflection. I wonder if is there a reflection library which make the use of java.lang.reflect easier.
We could use it like:
Reflected object = new Reflected( new Object() {
String name="Oscar";
String lastName="Reyes";
String reverseName(){
return new StringBuilder(name+lastName)
.reverse()
.toString();
}
int nameLength() {
return (name+lastName).length();
}
});
String name = object.getString("name");
object.set("name", "Mr. Oscar");
String reversed = ( String ) object.exec("reverseName");
int count = ( Integer ) object.exec("nameLength");
....
UnknownLibraryObject reflectionMadeEasy
= new UnknownLibraryObject( .... );// initialize with an object from somewhere
String someString = ( String ) reflectionMadeEasy.get("stringPropertyFromTheReflectedObject");
int someInteger = ( String ) reflectionMadeEady.execute("someMethodFromReflectedObject", 1,2,3 );// with args.
Do every project that use reflection start from the scratch or is there a library already for this?
It's not clear what you're trying to do, but Apache Commons Lang provides a number of convenient utilities classes to make reflection a bit less cumbersome, such as MethodUtils, FieldUtils and ConstructorUtils. These typically provide one-liners to abstract out the often bulky raw reflection code.
As #Lauri pointed out, Commons BeanUtils is also available, providing more high-level functions, such as copying properties between objects.
See also java.beans.Expression and java.beans.Statement.
Apache Commons Lang is as straight forward as it gets. There is also Whitebox which is PowerMock's Reflection Helper - here is the Quick Summary from the wiki.
Quick summary
Use Whitebox.setInternalState(..) to
set a private member of an instance or
class.
Use
Whitebox.getInternalState(..) to get a
private member of an instance or
class.
Use Whitebox.invokeMethod(..)
to invoke a private method of an
instance or class.
Use
Whitebox.invokeConstructor(..) to
create an instance of a class with a
private constructor.
I like it better than ACL as you don't have to be explicit with the staticness of the Fields and Methods.
Most convenient is jOOR, with it your code becomes:
Reflect.on(anyObject).field("stringPropertyFromTheReflectedObject").get()
Reflect.on(anyObject).call("someMethodFromReflectedObject", 1,2,3).get()
Spring Framework contains some helpers, not all that different from Commons Lang/BeanUtils ...
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/util/ReflectionUtils.html
http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/beans/BeanUtils.html
Both classes are marked as 'intended for internal use', but still worth a look.
You may even find that you're really looking for a framework such as Spring to manage your objects ... hth
I don't know, but if you find yourself using the standard Java reflection APIs a lot, maybe there is something not quite right about the way you design and implement Java programs.
Java is primarily designed as a staticly typed language, and works very well when used that way. While dynamic typing and (particularly) reflection can get you out of difficult problems, it is generally a good idea to restrict their use because:
they reduces performance,
they makes your source code more complex and less readable, and
they make your code more fragile.
Hiding the reflection behind a library layer or within a Sping-like framework addresses the readability issue but not the performance or fragility issues. (There are other approaches that do address all of the issues ... but without more information about why you are doing so much reflective programming, it is not clear they are relevant.)
For Spring Framework users. There are some utility classes to work with the reflection easier:
org.springframework.util.ReflectionUtils
org.springframework.util.ClassUtils
org.springframework.core.annotation.AnnotationUtils
org.springframework.util.TypeUtils

Categories

Resources