Mule Issue : More than one JAXBContext - jaxb

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.

Related

How to inject properties when using Castle Windsor

I am new to IOC.
I've MethodProfilerAspectAttribute attribute which has to be applied on any method like this
[MethodProfilerAspectAttribute(5)]
public void MethodName(){}
Here is the implementation of MethodProfilerAspectAttribute
[Serializable]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class MethodProfilerAspectAttribute : OnMethodBoundaryAspect
{
public ILogger logger { get; set; }
public int x{get;set;}
public MethodProfilerAspectAttribute(int x)
{
this.x=x;
}
public override void OnSuccess(MethodExecutionArgs args)
{
logger.CustomLogging("logMe");
base.OnSuccess(args);
}
}
I want to resolve my ILogger dependency using Log4NetLogger which is registered and resolving constructor dependencies properly by using following :
container.Register(Component.For<ILogger>().ImplementedBy(typeof(Log4NetLogger)));
but unfortunately whatever I've tried for resolving property dependency, is not working.
Any help would be greatly appreciated.
The link you provided just describes property injection for components resolved from the container. Attributes are not resolved from the container, but instead are created by the CLR. You might be able to jigger a way to set attribute properties by providing a custom IContributeComponentModelConstruction implementation, but I'm not so sure. See answers for similar questions here, here, and here (from the creator of Windsor).
In any case, attributes is not where you want to put functionality. They should be minimal, just providing metadata. I see here you're trying to provide some sort of functionality across all method invocations. You may want to consider Windsor's interceptors to provide similar behavior.

Rendering GORM classes from Spring Boot

I'm trying to write a simple Spring Boot controller that renders a GORM instance and failing.
Here's a shortened version of my code:
#RestController
#RequestMapping("/user")
class UserController {
#RequestMapping(value='/test', method=GET)
User test() {
return new User(username: 'my test username')
}
}
I get the following error message:
Could not write JSON: No serializer found for class org.springframework.validation.DefaultMessageCodesResolver and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: users.domain.User["errors"]->grails.validation.ValidationErrors["messageCodesResolver"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.springframework.validation.DefaultMessageCodesResolver and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: users.domain.User["errors"]->grails.validation.ValidationErrors["messageCodesResolver"])
The error seems to be caused by extra properties injected by GORM. What is the proposed solution for this? Will this eventually be solved in gorm-hibernate4-spring-boot? Should I simply disable SerializationFeature.FAIL_ON_EMPTY_BEANS (I don't have a lot of experience with Jackson so I'm not entirely sure what side effects this may have)? Should I use Jackson's annotations to solve the problem? Any other options?
I've found a way to get rid of the error using this code:
#Component
class ObjectMapperConfiguration implements InitializingBean {
#Autowired
ObjectMapper objectMapper
#Override
void afterPropertiesSet() {
def validationErrorsModule = new SimpleModule()
validationErrorsModule.addSerializer(ValidationErrors, new ErrorsSerializer())
objectMapper.registerModule(validationErrorsModule)
}
}
class ErrorsSerializer extends JsonSerializer<ValidationErrors> {
#Override
void serialize(ValidationErrors errors, JsonGenerator jgen, SerializerProvider provider) {
jgen.writeStartObject()
jgen.writeEndObject()
}
}
Obviously this solution is far from perfect as it simply nukes all validation errors but right now it is good enough for me. I am pretty sure the Spring Boot team will have to address this issue eventually as the GORM objects are also being serialized with some internal Hibernate properties like attached. I'm not accepting this answer as it is not an acceptable solution for most scenarios, it basically just squelches the exception.
This did not work for me.
So I used this instead and the error disappeared.
#JsonIgnoreProperties(["errors"])
I'm using springBootVersion '1.4.1.RELEASE' with gorm & hibernate5:
compile("org.grails:gorm-hibernate5-spring-boot:6.0.3.RELEASE")
I am having to include the following at the top of each domain class in order to use them in a client response (i.e. json serialization using jackson):
#JsonIgnoreProperties(["errors", "metaClass", "dirty", "attached", "dirtyPropertyNames"])
When using springBootVersion '1.3.5.RELEASE' I was able to get away with:
#JsonIgnoreProperties(["errors"])
This is trending in the wrong direction :)

Can CDI #Producer method take custom parameters?

I think i understood how CDI works and in order to dive deep in it, i would like to try using it with something real world example. I am stuck with one thing where i need your help to make me understand. I would really appreciate your help in this regard.
I have my own workflow framework developed using Java reflection API and XML configurations where based on specific type of "source" and "eventName" i load appropriate Module class and invoke "process" method on that. Everything is working fine in our project.
I got excited with CDI feature and wanted to give it try with workflow framework where i am planning inject Module class instead of loading them using Reflection etc...
Just to give you an idea, I will try to keep things simple here.
"Message.java" is a kind of Transfer Object which carries "Source" and "eventName", so that we can load module appropriately.
public class Message{
private String source;
private String eventName;
}
Module configurations are as below
<modules>
<module>
<source>A</source>
<eventName>validate</eventName>
<moduleClass>ValidatorModule</moduleClass>
</module>
<module>
<source>B</source>
<eventName>generate</eventName>
<moduleClass>GeneratorModule</moduleClass>
</module>
</modules>
ModuleLoader.java
public class ModuleLoader {
public void loadAndProcess(Message message){
String source=message.getSource();
String eventName=message.getEventName();
//Load Module based on above values.
}
}
Question
Now , if i want to implement same via CDI to inject me a Module (in ModuleLoader class), I can write Factory class with #Produce method , which can do that. BUT my question is,
a) how can pass Message Object to #Produce method to do lookup based on eventName and source ?
Can you please provide me suggestions ?
Thanks in advance.
This one is a little tricky because CDI doesn't work the same way as your custom solution (if I understand it correctly). CDI must have all the list of dependencies and resolutions for those dependencies at boot time, where your solution sounds like it finds everything at runtime where things may change. That being said there are a couple of things you could try.
You could try injecting an InjectionPoint as a parameter to a producer method and returning the correct object, or creating the correct type.
There's also creating your own extension of doing this and creating dependencies and wiring them all up in the extension (take a look at ProcessInjectionTarget, ProcessAnnotatedType, and 'AfterBeanDiscovery` events. These two quickstarts may also help get some ideas going.
I think you may be going down the wrong path regarding a producer. Instead it more than likely would be much better to use an observer especially based on what you've described.
I'm making the assumption that the "Message" transfer object is used abstractly like a system wide event where basically you fire the event and you would like some handler defined in your XML framework you've created to determine the correct manager for the event, instantiate it (if need be), and then call the class passing it the event.
#ApplicationScoped
public class MyMessageObserver {
public void handleMessageEvent(#Observes Message message) {
//Load Module based on above values and process the event
}
}
Now let's assume you want to utilize your original interface (I'll guess it looks like):
public interface IMessageHandler {
public void handleMessage(final Message message);
}
#ApplicationScoped
public class EventMessageHandler implements IMessageHandler {
#Inject
private Event<Message> messageEvent;
public void handleMessage(Message message) {
messageEvent.fire(message);
}
}
Then in any legacy class you want to use it:
#Inject
IMessageHandler handler;
This will allow you to do everything you've described.
May be you need somthing like that:
You need the qualifier. Annotation like #Module, which will take two paramters source and eventName; They should be non qualifier values. See docs.
Second you need a producer:
#Produces
#Module
public Module makeAmodule(InjectionPoint ip) {
// load the module, take source and eventName from ip
}
Inject at proper place like that:
#Inject
#Module(source="A", eventName="validate")
Module modulA;
There is only one issue with that solution, those modules must be dependent scope, otherwise system will inject same module regardles of source and eventName.
If you want to use scopes, then you need make source and eventName qualified parameters and:
make an extension for CDI, register programmatically producers
or make producer method for each and every possible combinations of source and eventName (I do not think it is nice)

JAXB is not picking up #XmlJavaTypeAdapter

I have the following class that I need to serialize as XML:
#XmlAccessorType(XmlAccessType.FIELD)
public class Position {
#XmlElement(name = "Quantity", required = true)
private DecimalQuantity quantity;
...
}
I have put an XmlJavaTypeAdapter on the DecimalQuantity class because I want it to be serialized simply as a BigDecimal without the DecimalQuantity wrapper.
#XmlJavaTypeAdapter(DecimalQuantityAdapter.class)
#Embeddable
public class DecimalQuantity {
private BigDecimal value;
...
}
Here's the very simple DecimalQuantityAdapter class:
public class DecimalQuantityAdapter
extends XmlAdapter<BigDecimal, DecimalQuantity> {
public DecimalQuantity unmarshal(BigDecimal val) throws Exception {
return new DecimalQuantity(val);
}
public BigDecimal marshal(DecimalQuantity val) throws Exception {
return val.getValue();
}
}
I have a unit test that shows that the adapter is working correctly. The following Order object that has a DecimalQuantity gets serialized correctly (notice that this test class looks almost identical to the Position class above):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Order")
public class Order {
#XmlElement(name = "Quantity", required = true)
private DecimalQuantity quantity;
...
}
This gets serialized as shown below - no wrapper around the decimal number - life is good!
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Order>
<Quantity>10.2</Quantity>
</Order>
The trouble starts when I try to use DecimalQuantity in other maven projects. For example, the Position class shown at the beginning of this post is in a different maven project. The web service that uses the Position class is in yet another maven project. When the web service tries to deserialize DecimalQuantity, it does not know what DecimalQuantity is and is not able to pick up the DecimalQuantityAdapter. This is the error I get:
Caused by: javax.xml.bind.JAXBException:
class org.archfirst.common.quantity.DecimalQuantity nor any of its super class is known to this context.
at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:594)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:648)
... 53 more
I have event tried to add the #XmlJavaTypeAdapter annotation on the attribute itself, but JAXB does not pick it up. The only way to get rid of the exception is to put an #XmlSeeAlso({DecimalQuantity.class}) on the Position class itself. However, this disables the adapter and I get the following (undesired) serialization:
<Quantity xsi:type="ns2:decimalQuantity" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
Any idea where the problem is? I feel it has something to do with the visibility of JAXB annotations on DecimalQuantity and DecimalQuantityAdapter across packages/projects.
Thanks.
Naresh
Ok, I finally found the problem. My unit test was picking up the JAXB implementation in the Java runtime, whereas my real application (a web service) was picking up the JAXB implementation from GlassFish. Apparently the implementation bundled with GlassFish (2.2.1.1) cannot handle my use case. I proved it by forcing my unit test to use jaxb-impl-2.2.1.1.jar. Also it seems that the bug has been fixed in the latest JAXB implementation (2.2.3-1), but I am struggling to figure out how to replace GlassFish's implementation with this new version (see my post here).
Are you sure the problem is with the XmlJavaTypeAdapter for decimals, not the DecimalQuantity type. Because the exception you've posted is the one that happens when JAXB encounters a value of unknown class.
What happens if you omit the #XmlJavaTypeAdapter annotation? I know it probably can't work the way you intend, but what is the error message? Isn't it the same?
As you wrote the exception is gone when you added:
#XmlSeeAlso({DecimalQuantity.class})
I would leave the annotation in the code and try to find the reason why the adapter doesn't work.
Can you debug in the your XML adapter and/or add some trace output there, just to make sure the adapter really returns a non-empty String?

JAXB cyclic reference avoidance using #XmlIDREF

I'm using JAXB in a web service with some slightly complex objects. One of the objects, Sensor, has a list of other objects it can communicate with, which necessarily can include itself (behavior that cannot be changed), leading to a cyclic reference during marshalling to XML.
#XmlAccessorType(XmlAccessType.FIELD)
public class Sensor extends BaseObject {
private ArrayList<SensorCommLink> sensorCommLinks;
}
#XmlAccessorType(XmlAccessType.FIELD)
public class SensorCommLink {
#XmlIDREF
private BaseObject receiver;
#XmlIDREF
private Sensor cueingSensor;
}
#XmlAccessorType(XmlAccessType.FIELD)
public abstract class BaseObject {
#XmlElement
#XmlID
private String id;
}
As shown above I solved this using #XmlIDREF and #XmlID and it works very nicely.
The client-side code generated via wsimport marshals the objects to XML and the server is able to unmarshal them perfectly.
The problem I'm experiencing is that for some reason on the server side I am getting a cyclic reference exception when I try to marshal a Sensor object. The maddening part is that the server-side code contains the JAXB annotations that are used by wsimport to create the client-side code, which works great, yet I can't marshal server-side Sensors due to the cycle.
I tried copying all of the extra annotations JAXB adds to the client-side code onto the server-side classes thinking perhaps there was a runtime bug in JAXB that was preventing it from properly applying the #XmlIDREF annotation. No luck there.
Perhaps there's something very basic I'm missing here but this issue is driving me a little batty and I'm at a dead stop while I try to figure it out.
One thing I did notice that I'm investigating is that some of the namespaces on the generated client-side objects aren't what I expected, though the code works. I'm curious to see if somehow a namespace issue on the server is causing the IDREF marshalling to bomb.
Any chance on the server side it is processing properties (get/set) instead of fields (instance variables). You can enforce field access in the following way:
#XmlAccessorType(XmlAccessType.FIELD)
public class SensorCommLink {
#XmlIDREF
private BaseObject receiver;
#XmlIDREF
private Sensor cueingSensor;
}
Or you could annotate the get methods.

Resources