What is JAXB and JAXRS ? How are they related? - jaxb

Sorry for this blunt question . But many use these 2 terms day in and day out yet I don't know .I did some study on this and knew what it is separately . But don't understand how it is related . I will share what I understood about these two first .
JAXB is XML-to-Java binding technology enabling transformations
between schema and Java objects and between XML instance documents
and Java object instances. Internally JAXB does all this conversions
between xml and java . This is a parser of xml and then it knows what
component in xml corresponds to what in java and it breaks .
Conversion of this answer from JAXB is done by tools like xjc ( or
codgen plugin) . Mapping may be like
xsd:string java.lang.String
xsd:integer java.math.BigInteger
JaxRs is different . This is set of specifications for handling
requests . Meaning that it says "GET("/foo") " means handle a get
call with url /foo . It only states that . How it is done ? Yes , that
is called implementation of this spec . There are number of
implementations like restlet , resteasy , jersey , apache cxf etc .
This is analogus to logic and way you implement in maths . the
algorithm idea is bucket search .This can be implemented in any way .
In java terms JaxRs is interface and these 4 restlet , resteasy ,
jersey , apache cxf are implementations of the interface .
Now please say if my understanding is correct . Then tell how they are related . Please help . If possible a pictorial explanation will be more helpful.

Your understanding is basically correct. JAXB and JAX-RS are both Java Community Process (JCP) standards with multiple implementations.
JAXB - Defines standardized metadata and runtime API for converting Java domain objects to/from XML.
JAX-RS - Defines standardized metadata and runtime API for the creation of RESTful services. By default for the application/xml media type JAX-RS will use JAXB to convert the objects to/from XML.
Example
In the following example when a GET operation is performed the JAX-RS implementation will return a Customer. A JAXB implementation will be used to convert that instance of Customer to the XML that the client will actually receive.
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
#Path("/customers")
public class CustomerResource {
#GET
#Produces(MediaType.APPLICATION_XML)
#Path("{id}")
public Customer read(#PathParam("id") int id) {
Customer customer = new Customer();
customer.setId(id);
customer.setFirstName("Jane");
customer.setLastName(null);
PhoneNumber pn = new PhoneNumber();
pn.setType("work");
pn.setValue("5551111");
customer.getPhoneNumbers().add(pn);
return customer;
}
}

Related

Spring Integration support for the Normalizer EIP

Spring Integration here. I was expecting to see a normalize(...) method off the IntegrationFlow DSL and was surprised to find there wasn't one (like .route(...) or .aggregate(...), etc.).
In fact, some digging on Google and the Spring Integration docs, and I can't seem to find any built-in support for the Normalizer EIP. So I've taken a crack at my own:
public class Normalizer extends AbstractTransformer {
private Class<?> targetClass;
private GenericConverter genericConverter;
public Normalizer(Class<?> targetClass, GenericConverter genericConverter) {
Optional<GenericConverter.ConvertiblePair> maybePair = genericConverter.getConvertibleTypes().stream()
.filter(convertiblePair -> !convertiblePair.getTargetType().equals(targetClass))
.findAny();
assert(maybePair.isEmpty());
this.targetClass = targetClass;
this.genericConverter = genericConverter;
}
#Override
protected Object doTransform(Message<?> message) {
Object inbound = message.getPayload();
return genericConverter.convert(inbound, TypeDescriptor.forObject(inbound), TypeDescriptor.valueOf(targetClass));
}
}
The idea is that Spring already provides the GenericConverter SPI for converting multiple source types to 1+ target type instance. We just need a specialized flavor of that that has the same target type for all convertible pairings. So here we extend AbstractTransformer and pass it one of these GenericConverters to use. During initialization we just verify that all the possible convertible pairs convert to the same targetClass specified for the Normalizer.
The idea is I could instantiate it like so:
#Bean
public Normalizer<Fizz> fizzNormalizer(GenericConverter fizzConverter) {
return new Normalizer(Fizz.class, fizzConverter);
}
And then put it in a flow:
IntegrationFlow someFlow = IntegrationFlows.from(someChannel())
.transform(fizzNormalizer())
// other components
.get();
While I believe this will work, before I start using it too heavily I want to make sure I'm not overlooking anything in the Spring Integration framework that will accomplish/satisfy the Normalizer EIP for me. No point in trying to reinvent the wheel and all that jazz. Thanks for any insight.
If you take a closer look into that EI pattern, then you see:
Use a Normalizer to route each message type through a custom Message Translator so that the resulting messages match a common format.
The crucial part of this pattern that it is a composed one with a router as input endpoint and a set of transformers for each inbound message type.
Since it is that kind of component which is data model dependent and more over the routing and transforming logic might differ from use-case to use-case, it is really hard to make an out-of-the-box single configurable component.
Therefore you need to investigate what type of routing you need to do to chose a proper one for input: https://docs.spring.io/spring-integration/docs/current/reference/html/message-routing.html#router
Then for every routed type you nee to implement respective transformer to produce a canonical data mode.
All of the can be just wrapped into a #MessagegingGateway API to hide the normalize behind so-called pattern implementation.
That's what I would do to follow that EI pattern recommendations.
However if your use-case is so simple as just convert from one type to another, so yes, then you can rely on the ConversionService. You register your custom Converter: https://docs.spring.io/spring-integration/docs/current/reference/html/endpoint.html#payload-type-conversion. And then just use a .convert(Class) API from IntegrationFlowDefinition.
But again: since there is no easy way to cover all the possible domain use-cases, we cannot provide an out-of-the-box Normalizer implementation.

Spring Integration - convert XML payload to JSON

I am creating a generic adapter which would take XML message (with namepace) and convert it to JSON. I can remove the namespace using xslt and then use org.json api to conver to JSON and there are some other transformation and using the SI flow -
return IntegrationFlows
.from(org.springframework.integration.jms.dsl.Jms.messageDrivenChannelAdapter(
org.springframework.integration.jms.dsl.Jms.container(this.queueConnFactory, this.queue)
.transactionManager(transactionManager()).get()))
.transform(dynamicEnricherImpl.get(enricherName), "enrich")
.handle(publisher, "publishMessage")
.get();
I am looking if the same can be achieved using SPring Integration inner classes like ObjectToJSON transformer to remove the XML namespace and convert it to JSON. Please suggest
I don't understand how you really do a conversion from XML to JSON. Would you mind to share some sample with your XSLT and that org.json? And of course, with an original XML and final JSON.
What I would do in Spring Integration is something like UnmarshallingTransformer where we create some domain model from the XML using Marshaller abstraction.
Then when we have already a Java POJO it is easy to call the mentioned ObjectToJsonTransformer and you'll get a JSON on the output.
It is also possible to apply a XPathTransformer to get some value from the XML and so on.
Please, read more about XML support in docs: https://docs.spring.io/spring-integration/docs/5.3.0.M4/reference/html/xml.html#xml

Spring Integration Object To Map Transformer

I am using SI 4.0 and trying to use object-to-map-transformer as below
<integration:object-to-map-transformer input-channel="inputChannel"
output-channel="outChannel" >
</integration:object-to-map-transformer>
I am sending a object like Person class on the inputChannel. But the moment I fire my test it fails with following error
Caused by: java.lang.IllegalStateException: Neither jackson-databind.jar,
nor jackson-mapper-asl.jar aren't presented in the classpath. at
org.springframework.integration.support.json.JacksonJsonUtils.<clinit>(JacksonJsonUtils.java:41)
I dont understand why it needs jackson. I looked at SI code and can see it needs Jackson class but why is this need - when I simply need to map a simple object to Map?
Thanks
The code to convert object to map looks like:
Map<String,Object> result = this.jsonObjectMapper.fromJson(this.jsonObjectMapper.toJson(payload), Map.class);
Since the out of the box implementation for the JsonObjectMapper is Jackson, it requires that the last one should be presented in the classpath.
We decided to use JSON notation for the Map presentation, since any object in JSON has map-based structure.
If you have another algorithm to do the same, the contribution is welcome!
Or you can simply implement your own Transformer with that logic and use it from generic <transformer>.

Partial objects with JAXB?

I'm working to create some services with JAX-RS, and am relatively new to JAXB (actually XML in general) so please don't assume I know the pre-requisites that I probably should know! Here's the questions: I want to send and receive "partial" objects in XML. That is, imagine one has an object (Java form, obviously) with:
class Thing { int x, String y, Customer z }
I want to be able to send an XML output that contains (dynamically chosen, so I can't use XmlTransient) just x, or just z, or x and y, but not z, or any other combination that suits my client. The point, obviously, is that sometimes the client doesn't need everything, so I can save some bandwidth (particularly with lists of deep, complex objects, which this example clearly doesn't illustrate!).
Also, for input, the same bandwidth argument applies; I would like to be able to have the client send just the particular fields that should be updated in, say, a PUT operation, and ignore the rest, then have the server "merge" those new values onto existing objects and leave the un-mentioned fields unchanged.
This seems to be supported in the Jackson JSON libraries (though I'm still working on it), but I'm having trouble finding it in JAXB. Any ideas?
One thought that I was pondering is whether one can do this in some way via Maps. If I created a Map (potentially nested Maps, for nested coplex objects) of what I want to send, could JAXB send that with a plausible structure? And if it could create such a map on input, I guess I could work through it to make the updates. Not perfect, but maybe?
And yes, I know that the "documents" that will be flying around will probably fail to comply with schemas, having missing fields and all that, but I'm ok with that, provided the infrastructure can be made to work.
Oh, and I know I could do this "manually" with SAX, StAX, or DOM parsing, but I'm hoping there's a rather more automatic way, particularly since JAXB handles the whole objects so effortlessly.
Cheers,
Toby
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) offerst this support through its object graph extension. Object graphs allow you to specify a subset of properties for the purposes of marshalling an unmarshalling. They may be created at runtime programatically:
// Create the Object Graph
ObjectGraph contactInfo = JAXBHelper.getJAXBContext(jc).createObjectGraph(Customer.class);
contactInfo.addAttributeNodes("name");
Subgraph location = contactInfo.addSubgraph("billingAddress");
location.addAttributeNodes("city", "province");
Subgraph simple = contactInfo.addSubgraph("phoneNumbers");
simple.addAttributeNodes("value");
// Output XML - Based on Object Graph
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, contactInfo);
marshaller.marshal(customer, System.out);
or statically on the class through annotations:
#XmlNamedObjectGraph(
name="contact info",
attributeNodes={
#XmlNamedAttributeNode("name"),
#XmlNamedAttributeNode(value="billingAddress", subgraph="location"),
#XmlNamedAttributeNode(value="phoneNumbers", subgraph="simple")
},
subgraphs={
#XmlNamedSubgraph(
name="location",
attributeNodes = {
#XmlNamedAttributeNode("city"),
#XmlNamedAttributeNode("province")
}
)
}
)
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
For More Information
http://blog.bdoughan.com/2013/03/moxys-object-graphs-partial-models-on.html
http://blog.bdoughan.com/2013/03/moxys-object-graphs-inputoutput-partial.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

how to specify a codec in apache camel mina

I'm trying to use the hl7codec in apache mina. I can see how to do it using spring e.g.
beans:bean id="hl7codec" class="org.apache.camel.component.hl7.HL7MLLPCodec"
beans:property name="charset" value="iso-8859-1"
/beans:bean
but can't figure out how to do it using POJO / DSL i.e. my route is specified as
from("mina:tcp://0.0.0.0:21110?sync=true&codec=#hl7codec")
.to("file://test");
but this can't resolve the #hl7codec id.
Given an allergy to Spring, can anyone suggest an alternative way of specifying the codec or replicating the Spring dependency injection?
If you are not using Spring at all, you need to enlist the hl7codec in the Camel registry. In pure Java you can do this by
SimpleRegistry reg = new SimpleRegistry();
reg.put("hl7codec", new MyCodecObject());
CamelContext context = new DefaultCamelContext(reg);
The Camel in Action book covers this in chapter 4, section 4.3.1

Resources