First of all, I want to say that Spring WS is very powerful framework. I've noticed it when version 1.0 beta was released. As everything in Spring it has good API, simple implementation model and as result it was very flexible. And this mean that you can easily introduce need changes and extensions without changing Spring WS source code.
From the beginning, the Spring WS team was saying that SpringWS should support not only low-level request processing, when you have some object that represents input XML document or build output XML document, but can use different mapping and translation libraries to make it for you. And here is a place for Jaxb.
To enable marshaling you need just to do few simple changes:
- Add
marshaller
bean oforg.springframework.oxm.jaxb.Jaxb2Marshaller
type:<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="classesToBeBound">
<list>
<value>GetImageRequest</value>
<value>GetImageResponse</value>
<value>AddImageRequest</value>
<value>AddImageResponse</value>
</list>
</property>
</bean> - Add Marshaling Method Endpoint Adapter to yours spring.xml:
<bean class="org.springframework.ws.server.endpoint.adapter.GenericMarshallingMethodEndpointAdapter">
<property name="marshaller" ref="marshaller"/>
<property name="unmarshaller" ref="marshaller"/>
</bean> - Well, that's all :)
And then, after some testing, I found that it would be nice to trim input text fields and do other post-marshalling operations. And I was sure there was a normal way to do that with rather Spring WS or Jaxb. After a few minutes of searching, I have found the way and had completely working code that was doing what I was needed.
The catch is that Jaxb
Unmarshaller
supports listeners and Spring's Jaxb2Marshaller
has a property unmarshallerListener
, that points your listener to Unmarshaller
's listeners. With only 3 lines of configuration we have own listener called on each unmarshalling:
<bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
....
<property name="unmarshallerListener">
<bean class="TargetHandlerUnmarshallerListener"/>
</property>
</bean>
Here is
TargetHandlerUnmarshallerListener
code:import javax.xml.bind.Unmarshaller;
public class TargetHandlerUnmarshallerListener extends Unmarshaller.Listener {
@Override public void afterUnmarshal(Object target, Object parent) {
super.afterUnmarshal(target, parent);
if (target instanceof PostPopulatedHandler) {
((PostPopulatedHandler) target).postPopulated();
}
}
}
In this class I override only
afterUnmarshal()
method, that is called after XML is transformed to the Java object. You can also override beforeUnmarshal()
method if you need.PostPopulatedHandler
is my own interface that expose only postPopulated()
method. Each class knows what to do after unmarshalling, and declares it in the postPopulated()
method. Of course, there can be used some annotation, but interface option is the most simple, easier and obvious way.So, some summary is next: Spring libraries are awesome, because they always provide very good API and you always can do what you need without changing library source code. Jaxb is awesome as well. I'm noticing this, because it's always hard to write good API, especially in multifunctional libraries.
No comments:
Post a Comment