I only want to marshall the data with JAXB to a file if the previously unmarshalled data has been changed by the user. I know that classes generated by JAXB don't have equals() method. Is there any simple way to determine whether the data has been changed after unmarshalling?
E.g. org.w3c.dom.Document has isEqualNode() method for this purpose.
So, JAXB does not produce classes it marshalls data from instances of classes or populates instances by unmarshalling xml. Usually the classes are generated prior to compile-time by XJC. One option is to update the classes to include an equals method. This is not a great idea since you generally don't want to update generated code in case you need to regenerate at a later date. So you could write a utility class that takes two instances of the classes and compares them.
This is for comparing after unmarshalling. Another option would be to perform a check prior to unmarshalling by doing a checksum on the file.
The best is probably to implement Comparator or utility classes to check equality.
You could for instance rely on commons-lang EqualsBuilder and CompareToBuilder.
One fairly standard approach is to add a transient boolean to the class, isDirty, and your setter methods will set that to true. (or, if you prefer, add a dateModified)
Obviously, this requires changing your internal class code which may be inappropriate.
You could also keep some Set of all objects that have been modified. But getting this logic correct may also be tricky or impossible depending on how your code is organized.
You can use the JAXB2 Basics Plug-in to have equals methods generated into your model classes:
http://confluence.highsource.org/display/J2B/JAXB2+Basics+Plugins
I have decided to marshal to a org.w3c.dom.Document and to use its isEqualNode()-method. If the original document differs from the new one then I marshal to a file. As I haven't so much XML data it works for me.
Related
I've got a problem with understanding the Freemarker Data Model and how to work with it correctly.
I currently have 1 Core Data Class.
It is stuffed as hell (a lot of variables with getters and setters) and I want to split it into different Classes.
But my Core Class is fueling a Freemarker processing... And I just don't get, how to get this working with several classes.
Currently I use this:
templateValues.process(config_generator.CDATA, stringWriter);
CDATA is my Core Data Class...
I checked the Freemarker guide several times, but I just don't get it.
If I would implement 2 Classes (CDATA1 & CDATA2 i.e.) how would I set up the processing? And would this work with even more Classes as well? (CDATA3 to X).
There's no such feature out of the box, but it's just the question of the TemplateHashModel implementation you pass in as the data model. (The data model is always a TemplateHashModel, though if you pass in a POJO FreeMarker will adapt it automatically via the ObjectWrapper in the Configuration.) You could easily write a TemplateHashModel implementation that encloses a list of other TemplateHashModel-s, and whose get(String) returns the requested variable from the first enclosed TemplateHashModel whose get(String) returns non-null. To adapt your POJO (CDATA1 etc.) to TemplateHashModel call cfg.getObjectWrapper().wrap(myObject), where cfg is the freemarker.template.Configuration object.
I'd like to save a Java object to file (for unit testing later on). I have tried JSON but since I don't own the classes to the objects I'm serializing, deserialization becomes more effort than it is worth. (The getters and setters to the existing classes are overloaded with different types and Jackson cannot figure out how to deserialize the object)
Now I'm exploring other avenues (i.e. serializing to binary or some other format). I'm wondering if there is anything out there that can dump a Java object to binary/file so that deserialization is trivial. I understand you can do this with the Serializable interface, but again I don't own these classes which don't implement this interface so they cannot be modified.
You could also use XStream which does not depents on classes having implemented Serializable interface.
if they implement Serializable you do not need to own them (nor modify them), you can just write them to file using an ObjectOutputStream and read them back in with a ObjectInputStream
Assuming the classes have proper getters and setters you should have no issue doing this
You can also use Kryo. Benchmarks (here and here) say it is one of the fastest to serialize/deserialize and uses less space too. It also doesn't need Serializable to be implemented. That said, I have never used it personally.
I would like to create a class in Java based on the fields defined in my XML config file:
For example: if the XML file contains (the syntax has been maligned for posting):
<property name="agent_host"></property>
<property name="subsystem"></property>
then internally it will create a class Event such as Event(String agentHost, String subSystem) that the client can instantiate. Note: the client always knows that this class will be called "Event" but does not know how many "mandatory parameters" it needs to pass.
On the other hand if I have a XML file with:
<property name="agent_host"></property>
then it will create Event(String eventHost) that the client can use for instantiation.
Yes, you could use reflection, but what comes to my mind is working with a class that you could add property.
Imagine a class that has one encapsulated HashMap using a String as a key (for the attribute name) and the value of the attribute so you could read the XML file and for evey property add the attribute to the class like.
For this line:
<property name="subsystem" type="String">value123</property>
GenericClass c = new GenericClass();
c.addAttribute("subsystem", new String("value123"));
//and you could implement a get and set methods like this:
public String getAttributeValue(String attributeName)
{
return internalHashMap.get(attributeName).toString();
}
Using this you could also implement a setAttributeValue
will be quite simple I think
If you really interested in creating a class dynamically, try Byte code Enhancement libraries like BCEL from Apache.
This isn't really a class you want, it's data. Why not use a hashmap? I really dislike "Bean" style classes--they encourage bad coding (there is no place in a generated class to put actual code, so everything ends up being manipulated by external code anyway).
You can just load a hashmap from your XML and inject it into a real object--that way you don't have to worry about actually passing a hash around, you are passing a real object with real business methods and real type safety--it just HAPPENS to use a hashmap internally to store data instead of member variables.
I've done a lot more than this, but at some point you realize Hibernate does everything you want for you.
I think the DynaBean from Commons-BeanUtils may be what you're looking for.
A DynaBean is a Java object that supports properties whose names and data types, as well as values, may be dynamically modified. To the maximum degree feasible, other components of the BeanUtils package will recognize such beans and treat them as standard JavaBeans for the purpose of retrieving and setting property values.
Out of curiosity, I'd like to know if any class exists in Java with a method that returns a copy of its data structure. I ask because in class the teacher said a method like this breaks privacy, but I think that getting a copy of the structure is useful if you want to rearrange the structure. I'd like an example. Thanks.
I'm not entirely sure what you mean by the "data structure" of a class, but assuming you mean the members it contains, what you're looking for is reflection.
Try this tutorial.
Maybe you are missing the point: If you build a class which encapsulates some kind of internal data then you should NOT add a method which returns the internal data structure, but only the data that is encapsulated.
(Which is kind of the idea of encapsulation)
There should not be any need to "rearrange" your internal representation from the outside - because it is supposed to be internal and thus transparent in its use. (Meaning: You should not even be able to say what kind of data structure is used)
If you serialize it, any object (that is serializable) will happily prints its internal structure to a binary stream. And yes, this breaks encapsulation.
And yes, no one stops you from going to change the binary output and read it in again to create an altered object.
NB: there are more strange issues regarding serialization. For example, when deserializing objects new objects are created without their constructor ever being called. Et cetera. Serialization of objects is the maybe least object-oriented thing one can do with objects.
You're mixing up some concepts here.
Classes really are "data structures + methods", so in general you'd need a class to represent your class. Hey, a nice custom-built one would be the class your data is already in. You may be thinking of a class as a collection of simple fields, but this is not always the case.
As others have mentioned, you can extract the data via reflection, e.g.
public Map<String,Object> fields() {
Map output=new hashMap<String,Object>();
for (Field f:getClass().getFields())
{
try{
output.put(f.getName(), f.get(this));
}
catch(... //IllegalArgument, IllegalAccess.. {... }
}
return output;
}
You can get into encapsulation issues here, in general the class should provide the data that you need to see from it, I tend to use things like this only for debugging.
I'm not sure what you mean by "rearrange the structure". The class generally represents the structure of the data. If there's a transformation you want to accomplish, it probably belongs in a class method, e.g. are you thinking of something like a co-ordinates class that can provide a transformed version of itself into polar co-ordinates?
A simple way to see the internal representation of an object is to serialise it using XStream. This will generate an XML representation of the class and its components (and so on).
Does this break encapsulation ? Yes - in the sense that you're able to inspect the internal structure of the class. You can take that XML, change it, and provided that it matches the .class structure that it came from, deserialise it back into a .class instance.
I have an XSD file which is used to generate some objects which are then shared with other systems. I'd like to customize some of the business logic a bit in there by making some more specific implementation of these. I'm not adding new fields which need to be serialized, but more along the lines of adding setMethods which may take different format parameters. These methods do the work of translating the data into a form which is needed by the underlying object.
I may have a field on the JAXB object which is a string, but my system gives me an integer. So, I want to handle the work of converting that in a class which extends my base class.
So, is there anything special you need to do in order to get JAXB to look for XmlRootElement on a subclass of the object you are asking it to serialize? Or must I include a #XmlRootElement attribute on my more specific class?
thanks!
Yes, #XmlRootElement/ #XmlType should be enough. But why don't you just add these methods to the generated classes? (in case you are not regenerating them on each build, which is wrong imo)
However I'd advice externalizing the conversion to other (converter) classes / methods.