Problem
I'm getting some strange behavior where the Spring Jaxb2Marshaller
doesn't scan my package-info.java
. Could anyone take a look?
I have a Spring MVC/Camel application that accepts multiple objects that are wrapped with a generic wrapper, where the XML MUST look like:
<mlf:message id="22" product="great.event" xmlns:mlf="special mlf URI">
<mlf:header>
<mlf:action value="notify-published"/>
</mlf:header>
<mlf:payload status="partial">
<can be any element at all>
</mlf:payload>
</mlf:message>
My setup follows the Error.
Error
-00:00 [localhost-startStop-1] ERROR o.s.web.context.ContextLoader Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jaxb2Marshaller' defined in class path resource [com/company/CamelConfig.class]: Invocation of init method failed; nested exception is
...
Exception [EclipseLink-25016] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.XMLMarshalException
Exception Description: A namespace for the prefix mlf:header was not found in the namespace resolver.
- with linked exception:
[Exception [EclipseLink-0] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.IntegrityException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553) ~[spring-beans-4.0.1.RELEASE.jar:4.0.1.RELEASE]
Setup
My package-info.java and Wrapper classes look like this:
package-info.java
@XmlSchema(
xmlns={
@XmlNs(prefix="mlf", namespaceURI="special mlf URI")
},
elementFormDefault=XmlNsForm.UNQUALIFIED)
package com.company.camel;
import javax.xml.bind.annotation.*;
Message.java
package com.company.camel;
@XmlRootElement(name = "message", namespace = "special mlf URI")
@XmlAccessorType(XmlAccessType.FIELD)
public class Message {
@XmlAttribute(required = false)
private int id;
@XmlAttribute(namespace = "")
private String product;
@XmlAttribute(namespace = "", required = false)
private String type;
@XmlPath("flm:header/flm:action/@value")
private String action;
@XmlPath("flm:header/flm:notify-failure/@type")
private String notifyFailureType;
@XmlPath("flm:header/flm:notify-failure/@value")
private String notifyFailureValue;
@XmlPath("flm:payload")
private Payload payload;
//SNIP
}
Payload.java
package com.company.camel;
@XmlRootElement(name="payload", namespace="special mlf URI")
@XmlAccessorType(XmlAccessType.FIELD)
public class Payload {
@XmlAttribute
private String status;
@XmlAnyElement(lax=true)
Object body;
//Getters&setters snipped
}
Because I need to unmarshal this class from Spring MVC REST and Camel (no I cannot use Camel for REST), I set up JAXB in Spring like this:
@Configuration
@ComponentScan(basePackages="com.company.camel")
public class CamelConfig extends CamelConfiguration
{
//SNIP
// The JAXBDataFormat is used inside Camel routes
@Bean
public JaxbDataFormat jaxbDataFormat() {
return new JaxbDataFormat(jaxb2Marshaller().getJaxbContext());
}
//used directly by Spring MVC
@Bean
public Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setPackagesToScan(new String[]{"com.company"});
return marshaller;
}