views:

349

answers:

6

Let's suggest that I have a bean defined in Spring:

<bean id="neatBean" class="com..." abstract="true">...</bean>

Then we have many clients, each of which have slightly different configuration for their 'neatBean'. The old way we would do it was to have a new file for each client (e.g., clientX_NeatFeature.xml) that contained a bunch of beans for this client (these are hand-edited and part of the code base):

<bean id="clientXNeatBean" parent="neatBean">
    <property id="whatever" value="something"/>
</bean>

Now, I want to have a UI where we can edit and redefine a client's neatBean on the fly.

My question is: given a neatBean, and a UI that can 'override' properties of this bean, what would be a straightforward way to serialize this to an XML file as we do [manually] today?

For example, if the user set property whatever to be "17" for client Y, I'd want to generate:

<bean id="clientYNeatBean" parent="neatBean">
    <property id="whatever" value="17"/>
</bean>

Note that moving this configuration to a different format (e.g., database, other-schema'd-xml) is an option, but not really an answer to the question at hand.

+2  A: 

I'd use Jax-b to do this. You'de create a bean object with a list of property objects inside.

@XmlRootElement(name = "bean")
@XmlAccessorType(XmlAccessType.FIELD)

public class Bean {

  @XmlAttribute
  private String id;
  @XmlAttribute
  private String parent;

  @XmlElement(name="property")
  private List<BeanProperty> properties

Then You'd need to also add annotations to BeanProperty. Then when you have a populated object simply marshal it to xml using jaxb:

Marshaller m = jc.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal( myBean, System.out );

For full code examples see: http://java.sun.com/webservices/docs/2.0/tutorial/doc/JAXBUsing.html

Alternatively you could use Groovy - you can drop it in place and creating this xml would be very simple... : http://www.ibm.com/developerworks/java/library/j-pg05199/index.html

Pablojim
Be careful generating all these objects automatically from the xsd - the resulting objects may contain many more objects and attributes than you need. Handcrafting a minimal set might be the best approach.
Pablojim
+4  A: 

You can download the Spring-beans 2.5 xsd from here and run xjc on it to generate the Java classes with JAXB bindings. Then you can create the Spring-beans object hierarchy on runtime (and manipulate it as you wish) and then serialize it to an XML string using the JAXB Marshaller as shown in Pablojim's answer.

abhin4v
This seems to be the best choice.... Although I was hoping for a library that would do it for me (surely someone else already solved this problem). Thanks for the input!
joeslice
+1  A: 

To add to the other two questions, I believe Spring already has a working model for bean definitions (see org.springframework.beans.factory.config.BeanDefinition); you could base your work on that.

alex
+1  A: 

I'd suggest using

<context:property-placeholder location="classpath*:clientX.properties"/>

and then in your bean def:

<bean id="${clientYNeatBeanId}" parent="neatBean">
    <property id="whatever" value="${whateverValue}"/>
</bean>

Then for each client you can have a clientX.properties containing

whateverValue=17
whateverAnotherValue=SomeText

.properties files are easier to edit both manually, and programaticalyl via java.util.Properties store(..) / save(..) methods

Bozho
I think the OP is about _generating_ bean definitions at runtime, not about setting property values at runtime.
abhin4v
I'm not entirely certain. I think he needs _one_ (or a few) such bean definitions, so he can use properties. but let's see.
Bozho
From the description of the use case, it sounds like properties should cover it. In addition, property files if following naming convention can be easily edited in parallel using localization editor like http://www.zaval.org/products/jrc-editor/user_guide/index.html
ddimitrov
This turns out to be approximately the same problem as defining the XML, just in a different format. I want to continue using the XML bean format for the time being.
joeslice
it's not the same. you have the same _bean definitions_, with _different properties_, depending on the environment.
Bozho
+3  A: 

If you want a simple to implement, no work solution, you can look at the IDE support provided in IntelliJ and Eclipse (The Spring Tool Suite).

They parse all the bean files (you can configure which set) and inspect the java code so it knows which classes there are, which properties are in those classes. Everywhere you can use Ctrl-Space to help with the options, etc...

I imagine you could setup 'projects' w/o Java code and only the spring config files in order to reduce the learning curve of front line personnel who must make these changes.

Peter Tillemans
Perhaps there is some library code that I could use as a starting point from within the Spring IDE. Currently, we use IDEs to author these beans, but I am planning to build a user-friendly (no XML) UI for this. Thanks for the suggestion!
joeslice
Good luck! I hope to see a blog post or something to see how it turned out.
Peter Tillemans
+1  A: 

What you need is obviously a factory for your neatBeans.

In Spring, instead of declaring a bean, you can declare a FactoryBean whose role is to actually create and configure your final bean. The NeatBeanFactoryBean could read a property file (or xml configuration) to determine how to configure the produced neatBeans, depending on some runtime parameter (the current clientID for example) or compile-time parameter (environment variable).

Olivier Croisier