I have some web service interfaces which uses WL JAXB to for XML processing. I need to perform following operation of Web Logic JAXB unmarshaller.
Unmarshaller unmarshaller = jc.createUnmarshaller();
unmarshaller.setEventHandler(validationCollector);
Any one know how to do it? Or is it possible?
Thank you in advance.
Lasith.
PS: I am using Weblogic 12c. With Eclipselink Moxy.
I think that I'm missing something...
Why don't you simply collect the event?
unmarshaller.setEventHandler(
new ValidationEventHandler() {
public boolean handleEvent(ValidationEvent event ) {
validationCollector.collectEvent(event);
}
});
Related
1) I would like to create a bean of HttpRequestExecutingMessageHandler (outbound channel adapter for HTTP) and specify the channel via an annotation like #OutboundChannelAdapter, why this is not possible? I suppose there is some design decision that I'm not understanding.
2) What is the suggested way of define HttpRequestExecutingMessageHandler without using XML configuration files? Do I have to configure the bean and set it manually?
Thanks in advance.
The #ServiceActivator fully covers that functionality. Unlike #Transformer it doesn't require a return value. So, your POJO method can be just void and the flow is going to stop there similar way a <outbound-channel-adapter> does that in XML configuration.
But in case of HttpRequestExecutingMessageHandler we need to worry about some extra option to make it one-way and stop there without care about any HTTP reply.
So, for the HttpRequestExecutingMessageHandler you need to declare a bean like:
#Bean
#ServiceActivator(inputChannel = )
public HttpRequestExecutingMessageHandler httpRequestExecutingMessageHandler() {
HttpRequestExecutingMessageHandler handler = new HttpRequestExecutingMessageHandler();
handler.setExpectReply(false)
return handler;
}
I think we need to improve docs on the matter anyway, but you can take a look into Java DSL configuration instead: https://docs.spring.io/spring-integration/docs/current/reference/html/#http-java-config. There is an Http.outboundChannelAdapter() for convenience.
We are facing one issue in our Mule Adapter related to JAXB context, needed some opinion on the same
We are using xpath to evaluate some expressions in the choice blocks in our adapter like below for instance,
<choice doc:name="Choice">
<when expression="//env:abc/env:Body/ref:dataelement/ref:/ref:element" evaluator="xpath">
......
</when>
Now, this works perfectly fine in our application but the problem arises when one of other team uses this Adapter as a jar in their application.
When they try to use this adapter, they are getting below error,
Message : More than one object of type class javax.xml.bind.JAXBContext registered but only one expected.
Type : org.mule.api.registry.RegistrationException
Code : MULE_ERROR--2
JavaDoc : http://www.mulesoft.org/docs/site/current3/apidocs/org/mule/api/registry /RegistrationException.html.
After debugging with the help of loggers etc, we narrowed down to the choice block used above which is causing this particular issue. Also, googled a bit and found one of the posts pointing out the same issue.
Also, to confirm we commented out the choice block having xpath expression and the flow went ahead but broke again where was xpath used in some other way.
https://www.mulesoft.org/jira/browse/MULE-5926
Can anyone please suggest any suitable workaround to resolve this issue?
I agree with you. It is an unresolved issue in Mule.
One solution we have implemented is not define the jaxb context in the config you are providing in the jar file.
Along with the jar file, give instructions to the end application using it, to include the JAXB packages in their JAXB Context object definition.
This way there will be only one JAXB context and it will work smoothly.
Hope this helps.
This is a bit late however the solution that worked was
<mulexml:jaxb-context name=“JAXB_Context“ packageNames=“org.example.test1:org.example.test2“ doc:name=“JAXB Context1“ />
Please note that there must be no space between package names.
Thanks to: http://dominikbial.de/quicktipp-working-with-more-than-one-package-name-in-a-jaxb-context-config-in-mule-esb/
As of now we cannot add more than one JAXBContext in mule. As an alternative you can write your custom transformer.
I implemented something like
public interface MyAppJaxbObj2XmlComponent<I,O> extends
MyAppComponent<I,O>,Callable {
public O marshal(I input) throws Exception;
}
Abstart transformer
public abstract class AbstractMyAppJaxbObj2XmlComponent<I,O> implements
MyAppJaxbObj2XmlComponent<I,O>{
private Class<I> inputType;
public AbstractMyAppJaxbObj2XmlComponent(){
this.inputType = (Class<I>) new TypeToken<I>(getClass())
{}.getRawType();
}
public AbstractMyAppJaxbObj2XmlComponent(Class<I> type){
this.inputType = type;
}
#Override
public Object onCall(MuleEventContext eventContext) throws Exception {
I input = eventContext.getMessage().getPayload(inputType);
O output = marshal(input);
return output;
}
}
Your flow transformer this will load your needed jaxb during startup.
#Component
public class MyFlowJaxbObj2XmlComponent extends
AbstractMyAppJaxbObj2XmlComponent<RequestPayloadType,String> {
#PostConstruct
public void init() {
//Load your schema during startup
}
}
You can also implement a fluid interface as an alternative for this.
I have java classes generated by XSD.
But when am trying to get JAXB context (while unmarshlling) it hits a dead end.
No errors,no print statements will be executed after this line. Nothing happens.
I have tried following methods
JAXBContext jc = JAXBContext.newInstance(package)
JAXBContext jc = JAXBContext.newInstance(class)
JAXBContext jc = JAXBContext.newInstance(package,contextloader)
but every option is failing.
Kindly suggest.
JAXBContext.newInstance will return you an instance of JAXBContext. From that you need to create instances of Unmarshaller to convert XML to objects, and instances of Marshaller to convert those objects back to XML.
I am trying to use jaxb in camel routing.I have tried to load router from xml using jaxb and got it done. Inside a method I have created jaxb object and unmarshaller the router in xml(loaded router from xml).
my code:
JAXBContext jaxb = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES);
Unmarshaller unmarshaller = jaxb.createUnmarshaller();
Resource rs = new ClassPathResource("cameltest.xml");
Object value = unmarshaller.unmarshal(rs.getInputStream());
RoutesDefinition routes = (RoutesDefinition) value;
context.addRouteDefinitions(routes.getRoutes());
Requirement:
Instead of doing it in java file. I need when a method in a service is called, the jaxb object inside the method should trigger off the xml which contains the flow (router concept). help me........
Using JAXB in a Camel route is quite easy, as is shown in JAXB. Unless the processing is very complex it can be done in Spring and requires a minimal amount of code.
What it looks like you are trying to do from the code is extract the routes using JAXB from the Camel xml file, perhaps you are wanting to create dynamic router - I would suggest looking at the EIP Patterns that Camel implements and picking something like the Content Based Router or Dynamic Router.
I have some #javax.xml.bind.annotation.Xml... annotated classes here intended for a RESt web service. Jersey is setup in a spring managed web container and the web service is returning a well formatted xml. We use the maven-enunciate-plugin to document the web service and create the xsd to the returned xml documents. I now would like to use the documentation xsd file as a schemaLocation within the returned xml file so that the xml validation won't complain about missing definions. How can I get the XML serialisation configured for this?
If I remember correctly, I had to do a few of things to get namespace identifiers properly written into my generated XML.
1) Created a JaxbFactory that configs and returns a custom marshaller (and unmarshaller, too, BTW). I'm omitting the getters/and unmarshalling setup below...
//constructor
public JaxbFactory() throws Exception {
context = JAXBContext.newInstance(ResourceDto.class);
// Setup the marshaller
marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, XmlMetadataConstants.XML_SCHEMA_LOCATION); // this schema location is used in generating the schema-location property in the xml
}
2) That factory class isn't "visible" to Jersey. To make it visible, I create a MarshallerProvider. That looks something like this:
#Provider
public class ResourceJaxbMarshallerProvider implements ContextResolver<Marshaller> {
// injected by Spring
private ResourceJaxbFactory ResourceJaxbFactory;
private ResourceStatusJaxbFactory ResourceStatusJaxbFactory;
/*
* ----------------------------------------
* Setters (for Spring injected properties)
* ----------------------------------------
*/
public void setResourceJaxbFactory(ResourceJaxbFactory ResourceJaxbFactory) {
this.ResourceJaxbFactory = ResourceJaxbFactory;
}
public void setResourceStatusJaxbFactory(ResourceStatusJaxbFactory ResourceStatusJaxbFactory) {
this.ResourceStatusJaxbFactory = ResourceStatusJaxbFactory;
}
/*
* ------------------------
* Interface Implementation
* ------------------------
*/
public Marshaller getContext(Class<?> type) {
if (type == ResourceDto.class)
return ResourceJaxbFactory.getMarshaller();
else if (type == ResourceStatusDto.class)
return ResourceStatusJaxbFactory.getMarshaller();
else
return null;
}
}
I've got Jersey wired into Spring using the Jersey/Spring Servlet so any #Provider class that gets created by Spring is automatically recognized by Jersey. In my Spring applicationContext.xml all I have to do is instantiate the resource provider. It will, in turn, go grab the marshaller from the factory.
3) The other thing that I found critical was that I had to create a package-info.java file in the root package containing my resource. Looks like this:
/*
* Note that this file is critical for ensuring that our ResourceDto object is
* marshalled/unmarshalled with the correct namespace. Without this, marshalled
* classes produce XML files without a namespace identifier
*/
#XmlSchema(namespace = XmlMetadataConstants.XML_SCHEMA_NAMESPACE, elementFormDefault = XmlNsForm.QUALIFIED)
package com.yourcompany.resource;
import javax.xml.bind.annotation.XmlNsForm;
At least I think that's everything I needed to do, I can't remember every single piece. I do remember that the package-info.java piece was the last critical cog that made it all come together.
Hope that helps. I spent wayyyy too much time digging for the info on all this. Jersey was seductively simple before I wanted it to do proper xml schema validation (and decent error reporting for schema-invalid input). Once I started down that road Jersey went from brain-dead easy to decently hard. The majority of that difficulty was sussing out all the details from the variety of posts online. Hopefully this will help get you farther, quicker. :-)