![](/img/trans.png)
[英]Exception in thread “main” javax.xml.bind.JAXBException: class nor any of its super class is known to this context
[英]javax.xml.bind.MarshalException - with linked exception: [javax.xml.bind.JAXBException: class ** nor any of its super class is known to this context
我有一個通用的Web服務,它期望一個WebServiceRequest
對象。 該對象具有類型為Object的有效負載。 以下是我的有效載荷的類型。
<xs:complexType name="payload">
<xs:sequence>
<xs:any processContents="lax"></xs:any>
</xs:sequence>
</xs:complexType>
我為Web服務輸入和輸出類型創建了JAXB
類。 因此對於有效負載,這是生成的字段。
@XmlAnyElement(lax = true)
private Object any;
下面是我的JAXB
生成的WebServiceRequest
VO的結構。
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "serviceRequest", namespace = "http://ws.test.svc.com/", propOrder = {
"payload"
})
public class WebServiceRequest{
@XmlElement
private Payload payload;
}
public class Payload{
@XmlAnyElement(lax = true)
private Object any;
}
我有一些自定義POJO,需要填充並設置為有效負載。 我使用以下注釋對這些POJO進行了注釋
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class AddressVO {
@XmlElement
private String pinCode;
@XmlElement
private String city;
}
我填充了此POJO的數據,並嘗試將其設置為WebServiceRequest
的有效負載。 但是當我這樣做時,我得到了以下異常。
javax.xml.bind.MarshalException
- with linked exception:
[javax.xml.bind.JAXBException: class com.vo.test.AddressVO nor any of its super class is known to this context.
您能否提出一些克服此問題的方法? 在一個鏈接中提到它包含@XmlSeeAlso
,但是由於我的有效負載非常通用,所以我不能這樣做。 在這方面請幫助我。
如果您無法應用@XMLSeeAlso
批注,則需要創建一個自定義MessageBodyReader
和MessageBodyWriter
,它們負責在Java和XML之間進行編組@XMLSeeAlso
。 在下面顯示了通用MessageBodyReader
的抽象實現,該實現實際上旨在執行特定於類型的XML驗證。 作者非常相似,因此未添加。
public abstract class AbstractXmlValidationReader<T> implements
MessageBodyReader<T> {
private final Providers providers;
private final Schema schema;
public AbstractXmlValidationReader(final Providers providers,
final ServletContext servletContext, final String xsdFileName) {
this.providers = providers;
try {
SchemaFactory sf = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
File xsd = new File(servletContext.getRealPath(xsdFileName));
schema = sf.newSchema(xsd);
} catch (Exception e) {
throw new RuntimeException(
"Unable to create XSD validation schema", e);
}
}
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
@SuppressWarnings("unchecked")
Class<T> readableClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
if (type == readableClass
&& type.isAnnotationPresent(XmlRootElement.class)) {
return true;
}
return false;
}
@Override
public T readFrom(Class<T> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
try {
JAXBContext jaxbContext = null;
ContextResolver<JAXBContext> resolver = providers
.getContextResolver(JAXBContext.class, mediaType);
if (null != resolver) {
jaxbContext = resolver.getContext(type);
}
if (null == jaxbContext) {
jaxbContext = JAXBContext.newInstance(type);
}
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
@SuppressWarnings("unchecked")
T entity = (T) unmarshaller.unmarshal(entityStream);
return entity;
} catch (JAXBException e) {
throw new MessageBodyReaderValidationException(
"Failure while performing xml validation or xml marhalling!",
e);
}
}
}
還有一個Address
類型的concreate實現
@Provider
@Consumes(MediaType.APPLICATION_XML)
public class AddressXmlValidationReader extends
AbstractXmlValidationReader<Address> {
private final static String xsdFileName = "/xsd/Address.xsd";
public AddressXmlValidationReader(@Context Providers providers,
@Context ServletContext servletContext) {
super(providers, servletContext, xsdFileName);
}
}
您現在需要的是MessageBodyReader
的slighlty修改后的readFrom
方法,如下所示。 對於MessageBodyWriter
該方法稱為writeTo
。
@Override
public T readFrom(Class<T> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
try {
JAXBContext jaxbContext = null;
ContextResolver<JAXBContext> resolver = providers
.getContextResolver(JAXBContext.class, mediaType);
if(entityStream != null){
// TODO read the entityStream and determine the concrete type of the XML content
type = ... ;
}
if (null != resolver) {
jaxbContext = resolver.getContext(type);
}
if (null == jaxbContext) {
jaxbContext = JAXBContext.newInstance(type);
}
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
unmarshaller.setSchema(schema);
@SuppressWarnings("unchecked")
T entity = (T) unmarshaller.unmarshal(entityStream);
return entity;
} catch (JAXBException e) {
throw new MessageBodyReaderValidationException(
"Failure while performing xml validation or xml marhalling!",
e);
}
}
使用這種方法,您可以通過Reader和Writer實例的具體子類定義通用類型。 一個可能更具體的類型可以在抽象基類中確定(例如在此示例中),也可以從其他地方注入它。 當然,您可以修改此MessageBodyReader
以便在某處或以其他方式確定XML輸入的具體類型。 但總的來說,這就是解決問題的方式。
注意:
不要忘記在Web服務Application
類中注冊具體的Reader和writer實現。
@ApplicationPath("/services")
public class WSApplication extends Application {
private Set<Object> singletons = new HashSet<Object>();
private Set<Class<?>> classes = new HashSet<Class<?>>();
public WSApplication() {
...
classes.add(AddressXmlValidationReader.class);
...
}
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.