Creating a network of objects from custom XML config with Spring - java

I have a custom XML config defining a kind of network like this
S1 ---- O1 ---- O2 ---- O3 ---- T1
\
+--- O4 ---- O5 ------------ T2
\
S2---+- O6 --+- O7 ------------ T4
/ /
S3-+ /
/
S4 ------+
Where
S is some kind of data source, like a web socket
O is an operator processing the data
T is the target or data sink
These elements are represented with xml blocks like this:
<source name="S1" address="ws://example/1" type="websocket" dataType="double" />
<operator name="O6" type="threshold">
<input name="S1"/>
<input name="S2"/>
<input name="S3"/>
<property name="threshold" value="10.34" />
<property name="window" value="10.0" />
</operator>
<sink name="T1" type="database">
<input name="O3"/>
</sink>
The dependencies are constructor parameters. My example operator O6 would have a constructor like this:
class ThresholdOperator extends Operator<Boolean> {
public ThresholdOperator(
String name, // "O6"
List<DataSource> sources, // [S1, S2, S3]
double threshold, // 10.34
double window) { // 10.0
...
There could be multiple instances of this class with different constructor parameters. It is possible that a class has more than one constructor. The type parameter of the base class is the output type.
The type attribute determines what concrete class has to be instantiated. The dataType attribute of the source decides which kind of converter (here String to Double) should be injected.
To create the instances I need to figurare out a dependency graph and start instantiating the objects without other objects from my graph as dependency (the sources in this case), then I would create the objects which depend only on objects created in the first step and so on.
So I would basically reinvent something like Spring for my special use case. Is there a way to leverage Spring to create and wire objects in my case? A somewhat crude hack would be to transform my xml config to a beans.xml. But maybe there is a better way using BeanFactory or the like. Or would it be possible to create the Spring meta-model directly?
I'm using Spring 4.3 but the RC of Spring 5 could be an option, if it would help.

Another alternative not yet mentioned here is using XSLT.
The idea is to define xsl that maps your domain-specific xml to spring beans xml (XSLT+XPath should be more than enough to cover your case).
You can then read domain-specific xml, transform it with that xsl and feed the result to spring.

Have a look on StaticApplicationContext. It is stated in the docs that it is:
Mainly useful for testing.
... but it is a full fledged application context that has support for programmatic bean registration.
You can read your domain-specific xml and define beans based on it inside StaticApplicationContext.
This blog post can give you an idea on how to use StaticApplicationContext to define beans with references and constructor args.

A simpler approach to instantiate your objects from the document would be to either
create an XML Schema describing your data format and using JAXB to create your Java classes
annotate your existing Java classes with JAXB annotations

The "crud" hack approach may be a better approach but instead of converting your config xml to beans xml file manually, I suggest you to look at the Extensible XML authoring approach.
The configuration parser, a.k.a. bean definition parser, allows you to build the bean definitions which will eventually be used your application's spring context to instantiate the beans.
This should also eliminate the needs of figuring out the dependency hierarchy manually and instantiation of objects yourself.
Hope it answer your question.

Related

How to structure Spring code for JAXB marhalling and proccessing of XML

The Question
I'm new to Java and spring and I'd like to know how to structure code which marshals different objects from XML and then processes them. I'm converting some code JAVA code from before my time to use spring. I know the way I've approached this this probably, wrong but If someone could offer a few pointers on how to restructure things "the Spring way" that would help alot. I've read a lot of the Spring docs, but I'm finding it hard to apply what is in there to my code.
The Situation
I'm not going to post the whole code tree as even and simple example is a lot of code (which is the problem). So I'll just describe the method.
I've got XML and schemas for two classes CLASSA & CLASSB. I've generated JAVA wrappers using xjc. I've got a JAVA class which is a wrapper for the JAXB marshaller. The wrapper needs to be given the class name and the package name of the class to be marshalled on construction.
public JaxbWrapper(String ClassName, String packageName) throws ClassNotFoundException, InstantiationException,
IllegalAccessException, JAXBException
{
this.packageName = packageName;
// set the context is the expensive operation
setJAXBContext(Class.forName(fullJaxbClassName(ClassName)).newInstance());
// get the schma from preset schema dir
schemaFileName = findSchema(ClassName);
myMarsheller = jc.createMarshaller();
myMarsheller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
}
I've then got one bean for each instance of the JaxBWrapper for both ClassA and ClassB. They are almost identical so only the one for class A is shown.
<bean id="jaxbParser_CLASSA" class="org.test.JAXB.JaxbWrapper"
lazy-init="true" scope="prototype">
<constructor-arg index="0" type="java.lang.String"
value="CLASSA" />
<constructor-arg index="1" type="java.lang.String"
ref="testPackage" />
<property name="encoding" ref="xmlEncoding" />
</bean>
Unhelpfully the XML files I have to process are delivered one at a time in file with a fixed name and a rolling counter (and I cannot change that). So I'm unable to tell what object is in the file from the filename. I've have a tiny utility function which check which the object type is in the file I'm trying to process.
I then have the following function:
public static Object loadXML(String xmlFile, String fileName) throws Exception
{
InputStream iStream = XmlUtils.openFile(xmlFile);
String xmlObjectType = XmlUtils.getObjectTypeFromXML(xmlFile);
// get the right JAXB processor
JaxbWrapper jaxB = myContext.getBean("jaxbParser_" + xmlObjectType , JaxbWrapper.class);
Object obj = jaxB.objectFromXML(iStream, xmlObjectType , fileName);
return obj;
}
So I'm taking the object name and getting the right bean from the context. This means I could use things like Spring's object pool to hold lots of JaxbWrappers for different objects. However the way I've implemented this feels wrong to me. I don't like the myContext.getBean("jaxbParser_" + xmlObjectType method of getting the JaxbWrapper bean.
So my question is: Is there a better way of structuring this code? A few simple pointers would be very much appreciated.
Additional Complexity
This is where things, at the moment, become really unmanageable. Once the marshaling stage has completed I've got a post processing stage where there are several different post processor for each class type. I've got Spring beans for each of these and I'm getting them from the application context using:
myContext.getBean(xmlObjectType + "_" + processorType + "_" + xmlObjectType);
where:
xmlObjectType is a string CLASSA or CLASSB which is set by reading the object type from the file (as above).
processorType is s string which is set from the comand line.
To set the proceesorType I'm doing something like the following when the application starts.
if (line.hasOption("file"))
{
processorType = "FileProcessor";
}
if (line.hasOption("print"))
{
processorType = "PrintProcessor";
}
Again, I don't think this is the right way to do things, but It's the best I've got at the moment :-(.
I guess the more general question is how do JAXB and Spring work together? In the real world I have lots very large and complex CLASSA and CLASSBs. I've got java classes for these generated by xjc. As I'm using xjc I have to use jaxb (I guess). The question is how to do that in the Spring world.
Or can I get rid of JAXB and use a spring component. I'd need to use something else to generate all the classes other than xjc. But I cannot find anything that would perform that task
There is a lot of stuff going on here and I have to agree with #BlaiseDoughan you should be able to do this outside of Spring.
Although Spring does do object pooling (aop) and has some management for throw away objects you should not use it for such. Basically anytime your doing getBean during runtime unless your know what your doing your doing it wrong.
Spring is for managing behavior based singletons.
So what you want to do is think how can make a singleton that does the behavior... In your case you want to make a Factory of JaxbWrapper.class (and I don't mean Spring's special bean Factory).
So something like:
public class JaxbWrapperFactory {
Map<String, JaxbWrapper> pool = new ConcurrentHashMap(); // recommend Guava's Cache
public JaxbWrapper create(String ClassName, String packageName) throws ClassNotFoundException, InstantiationException { }
public Object loadXML(String xmlFile, String fileName) throws Exception {
/// use create from above
}
}
Now in Spring you can only wire JaxbWrapperFactory.
If you want to make different strategies for create JaxbWrapper based on the input xml you could make sort of strategy interface and wire in the implementations. But I don't think you need that complexity.
Basically to boil it down these tips:
Be-aware that singletons and most spring managed beans must be thread safe.
Reserve public static methods for utility only as this leads to evil singletons.
Often times for object creation its best to make your own factory pattern.
You might want to take a look at JAXB's factory support.

Jackson - Deserializing to a Different Type

Using Jackson, how can I have JSON serialized/deserialized by one application using one set of classes, but have another application deserialize the same JSON and load different implementations of those classes?
I have a (Spring MVC) web application that allows users to define steps in a script, that in turn will be executed in a client application. Steps might be things like ShowDialogStep, with properties like dialogText, or WaitStep with a property of duration.
The client application will load collections of steps from the server. However, the classes instantiated by the client need to have execution-specific functionality like execute(), which in the case of WaitStep will keep a track of how far through waiting it is. Clearly the server-side application never needs know about this, and in less trivial examples the execute/update logic of a steps involves all manner of client-specific dependencies.
So, to recap I need:
The server application to map the 'prototype' classes to JSON;
The client application to read the same JSON but instantiate execution-specific classes instead of the 'prototype' ones.
Would this be something that could be configured on the client-side mapper, perhaps if the JSON was serialized using relative class names (rather than fully-qualified) then the deserializer could be configured to look in a different package for the implementations with execution logic in them?
You can use this approach:
On the server side:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property="#type")
class Prototype {
...
}
objectMapper.registerSubtypes(
new NamedType(Prototype.class, "Execution"),
...
);
then it will serialize a Prototype instance and add a type of bean:
{
"#type" : "Execution",
...
}
on the client-side:
#JsonTypeInfo(use=JsonTypeInfo.Id.NAME,
include=JsonTypeInfo.As.PROPERTY, property="#type")
class Execution {
...
}
objectMapper.registerSubtypes(
new NamedType(Execution.class, "Execution"), // the same name
....
);
objectMapper.readValue(....); // will be deserialized to an Execution instance

JAXB Factory for JPA entities

In most of my previous projects I have two domain models, one with JAXB annotations and the other one with JPA annotations. I know they can combined into one model with both annotations in the same class, but in my experiences the tradeoffs with this approach always came to the conclusion to separate them. Another advantage of a separate approach is the ability to create the JAXB classes with a XSD and easily link in XSDs from other projects.
In most cases I need factory classes being able for flexible creation of JAXB representations of my entities, e.g.
public class UserFactory
{
public UserFactory(User queryUser, String lang)
{
this.queryUser=queryUser;
this.lang=lang;
}
public JaxbUser getUser(JpaUser jpaUser)
{
JaxbUser jaxbUser = new JaxbUser();
if(queryUser.isSetId()){jaxbUser.setId(jpaUser.getId());}
if(queryUser.isSetEmail()){jaxbUser.setEmail(jpaUser.getEmail());}
if(queryUser.isSetRoles())
{
RolesFactory f = new RolesFactory(queryUser.getRoles(),lang);
jaxbUser.setRoles(f.getRoles(jpaUser.getRoles()));
}
return jaxbUser;
}
}
I create a UserFactory with an individual template queryUser and the desired lang for entities supporting different languages. The template is checked during creation of the result for specific fields or additional factories and the resulting object is created. The query is defined in a XML file like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<query lang="en">
<user id="1">
<roles>
<role code="code"/>
</roles>
</user>
</query>
With this methodology I have a powerful and flexible tool to create customized XML, despite all drawback of maintaining two domain models and the factory classes. I know there are many frameworks or libraries available which I never have heard about, so here my question:
Is there something available similar to my approach?
There are basically two options:
JPA and JAXB annotations on the same classes (see Hyperjaxb3 or DataNucleus)
Or you keepm the separated and write code to map one onto another
I personally do not see much added value in the cross-model mapping code. Usage of factories also does not seem too innovative, it is just a question of programming technique which you use to map one onto another.

Generate Spring bean definition from a Java object

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.
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.
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
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.
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).
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.
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

Java: which configuration framework to use?

I need to decide which configuration framework to use. At the moment I am thinking between using properties files and XML files. My configuration needs to have some primitive grouping, e.g. in XML format would be something like:
<configuration>
<group name="abc">
<param1>value1</param1>
<param2>value2</param2>
</group>
<group name="def">
<param3>value3</param3>
<param4>value4</param4>
</group>
</configuration>
or a properties file (something similar to log4j.properties):
group.abc.param1 = value1
group.abc.param2 = value2
group.def.param3 = value3
group.def.param4 = value4
I need bi-directional (read and write) configuration library/framework. Nice feature would be - that I could read out somehow different configuration groups as different objects, so I could later pass them to different places, e.g. - reading everything what belongs to group "abc" as one object and "def" as another. If that is not possible I can always split single configuration object into smaller ones myself in the application initialization part of course.
Which framework would best fit for me?
Since you are saying that it is possible to also store objects in the config, I would suggest this:
http://commons.apache.org/configuration/
The simplest way to do this would be to use Simple XML. It can bind XML to Java POJOs in a very simple manner. Also, it is much faster than other such XML binding frameworks.
http://simple.sourceforge.net
Only 270K with no dependencies.
Please take a look at this URL: http://issues.apache.org/jira/browse/CONFIGURATION-394
The Configuration framework which we're looking for it is something on top of Apache Commons Configuration and must support Concurrency Issues, JMX issues and most of stores(e.g .properties file, .xml files or PreferencesAPI).
What weblogic team provides on 'Administration Console' is intersting which through it you can have transactional(atomic) updates on configurations so that are registered listeners be notified.
The Apache guys insist that this project is out of scopes of Commons Configuration, maybe!
I've attached a simple configuration framework, take look please

Categories