views:

327

answers:

3

I need a way to bind POJO objects to an external entity, that could be XML, YAML, structured text or anything easy to write and maintain in order to create Mock data for unit testing and TDD. Below are some libraries I tried, but the main problems with them were that I am stuck (for at least more 3 months) to Java 1.4. I'd like any insights on what I could use instead, with as low overhead and upfront setup (like using Schemas or DTDs, for instance) as possible and without complex XML. Here are the libraries I really like (but that apparently doesn't work with 1.4 or doesn't support constructors - you gotta have setters):

RE-JAXB (or Really Easy Java XML Bindings)

http://jvalentino.blogspot.com/2008/07/in-response-to-easiest-java-xml-binding.html http://sourceforge.net/projects/rejaxb/

Seamlessy binds this:

<item>
    <title>Astronauts' Dirty Laundry</title>
    <link>http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp&lt;/link&gt;
    <description>Compared to earlier spacecraft, the International Space
    Station has many luxuries, but laundry facilities are not one of them.
    Instead, astronauts have other options.</description>
    <pubDate>Tue, 20 May 2003 08:56:02 GMT</pubDate>
    <guid>http://liftoff.msfc.nasa.gov/2003/05/20.html#item570&lt;/guid&gt;
</item>

To this:

@ClassXmlNodeName("item")
public class Item {
 private String title;
 private String link;
 private String description;
     private String pubDate;
     private String guid;

     //getters and settings go here... 
}

Using:

Rss rss = new Rss();
XmlBinderFactory.newInstance().bind(rss, new File("Rss2Test.xml"));

Problem: It relies on annotations, so no good for Java 1.4

jYaml http://jyaml.sourceforge.net/

Seamlessly binds this:

--- !user
name: Felipe Coury
password: felipe
modules: 
   - !module
     id: 1
     name: Main Menu
     admin: !user
    name: Admin
    password: password

To this:

public class User {
    private String name;
    private String password;
    private List modules;
}

public class Module {
    private int id;
    private String name;
    private User admin;
}

Using:

YamlReader reader = new YamlReader(new FileReader("example.yaml"));
reader.getConfig().setClassTag("user", User.class);
reader.getConfig().setClassTag("module", Module.class);
User user = (User) reader.read(User.class);

Problem: It won't work with constructors (so no good for immutable objects). I'd have to either change my objects or write custom code por handling the YAML parsing.

Remember that I would like to avoid - as much as I can - writing data descriptors, I'd like something that "just works".

Do you have any suggestions?

+1  A: 

If the objects to be populated are simple beans it may be a good idea to look at apache common's BeanUtils class. The populate() method might suit the described cases. Generally dependency injection frameworks like Spring can be very useful, but that might not be answer for the current problem. For input in form of xml, jibx might be a good alternative, so would be jaxb 1.0.

questzen
Just briefly looked and jibx, and it seems to be quite simple, I'll look further. Thanks for now.
kolrie
A: 

Just use XStream (for XML or you could give a try to JSON).

But...

Man, I just can't avoid to think that put the test data outside the unit test itself will leads you to unreadable tests. You will need look two files when reading a test case, you will lose refactoring tools (when changing property's name). Jay Fields can explain it better than me:

http://blog.jayfields.com/2007/06/testing-inline-setup.html

Kind Regards

marcospereira
EXACTLY my point with my team! But they insisted. I currently do it using Fluent Interfaces mixed with the Builder pattern and (at least I) love it! :-)
kolrie
A: 

You may give it a try to the deefault XMLEncoder/XMLDecoder that was added to the platform in Java1.4

Here's the way I use it.

import java.beans.XMLEncoder;
import java.beans.XMLDecoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class ToXml {

    /**
     * Write an object to a file in XML format.
     * @param o - The object to serialize.
     * @param file - The file where to write the object.
     */
    public static void writeObject( Object o, String file  ) {
       XMLEncoder e = null;
       try {

           e = new XMLEncoder( new BufferedOutputStream( new FileOutputStream(file)));

           e.writeObject(o);

       }catch( IOException ioe ) {
           throw new RuntimeException( ioe );
       }finally{
           if( e != null ) {
               e.close();
           }
       }
    }

    /**
     * Read a xml serialized object from the specified file.
     * @param file - The file where the serialized xml version of the object is.
     * @return  The object represented by the xmlfile.
     */
    public static Object readObject( String file ){
       XMLDecoder d = null;
       try {

           d = new XMLDecoder( new BufferedInputStream( new FileInputStream(file)));

           return  d.readObject();

       }catch( IOException ioe ) {
           throw new RuntimeException( ioe );
       }finally{
           if( d != null ) {
               d.close();
           }
       }
    }

}

It's easy, is simple, is in the core libraries.

You just have to write the load mechanism.

I have this swing app that loads data from a remote EJB in 5 - 10 secs. What I do is to store the previous session in XML like this and when the app loads it has all the data from the previous session in less than 1 sec.

While the user start to work with the app, a background thread fetches those elements that have changed since the last session.

OscarRyz