2012-12-27 19 views
26

Tôi đang cố truyền một đối tượng qua dịch vụ web REST. Sau đây là các lớp của tôi giải thích chức năng mà tôi cần sử dụng một số mã mẫu.javax.xml.bind.JAXBException: Lớp *** cũng như bất kỳ siêu lớp nào của nó được biết đến trong ngữ cảnh này

Nghỉ ngơi Web Service Lớp phương pháp

@POST 
@Path("/find") 
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) 
@Produces({MediaType.APPLICATION_JSON}) 
public Response getDepartments(){ 
    Response response = new Response(); 

    try { 

     response.setCode(MessageCode.SUCCESS); 
     response.setMessage("Department Names"); 
     Department dept = new Department("12", "Financial"); 
     response.setPayload(dept); 

    } catch (Exception e) { 
     response.setCode(MessageCode.ERROR); 
     response.setMessage(e.getMessage()); 
     e.printStackTrace(); 
    }  
    return response; 
} 

đáp ứng Lớp

import java.io.Serializable; 
import javax.xml.bind.annotation.XmlRootElement; 

@XmlRootElement 

public class Response implements Serializable{ 

    private static final long serialVersionUID = 1L; 

    public enum MessageCode { 
     SUCCESS, ERROR, UNKNOWN 
    } 

    private MessageCode code; 
    private String message; 
    private Object payload; 

    public MessageCode getCode() { 
     return code; 
    } 

    public void setCode(MessageCode code) { 
     this.code = code; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

    public Object getPayload() { 
     return payload; 
    } 

    public void setPayload(Object payload) { 
     this.payload = payload; 
    } 
} 

cục Lớp

@XmlRootElement 
public class Department implements java.io.Serializable { 


    private String deptNo; 
    private String deptName; 


    public Department() { 
    } 

    public Department(String deptNo, String deptName) { 
     this.deptNo = deptNo; 
     this.deptName = deptName; 
    } 

    public String getDeptNo() { 
     return this.deptNo; 
    } 

    public void setDeptNo(String deptNo) { 
     this.deptNo = deptNo; 
    } 

    public String getDeptName() { 
     return this.deptName; 
    } 

    public void setDeptName(String deptName) { 
     this.deptName = deptName; 
    } 

} 

Khi tôi thực hiện cuộc gọi đến phương thức getDepartments trong lớp dịch vụ web còn lại, nó trả về các ngoại lệ sau. Nhưng nếu tôi thay đổi loại Đối tượng của số trọng tải đến Sở trong lớp Phản hồi, nó trả về phản hồi json một cách chính xác. Nhưng vì tôi cần sử dụng lớp Response này cho các kiểu lớp khác nhau nên tôi không thể giữ lại tải trọng cho một kiểu lớp. Bất cứ ai có thể vui lòng giúp tôi trong vấn đề này?

Stack Trace

Dec 27, 2012 9:34:18 PM com.sun.jersey.spi.container.ContainerResponse logException 
SEVERE: Mapped exception to response: 500 (Internal Server Error) 
javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException 
- with linked exception: 
[javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.] 
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:159) 
    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:306) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1437) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349) 
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339) 
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537) 
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) 
    at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511) 
    at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401) 
    at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) 
    at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182) 
    at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766) 
    at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450) 
    at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) 
    at org.mortbay.jetty.Server.handle(Server.java:326) 
    at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542) 
    at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:945) 
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756) 
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 
Caused by: javax.xml.bind.MarshalException 
- with linked exception: 
[javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context.] 
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:323) 
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:177) 
    at com.sun.jersey.json.impl.BaseJSONMarshaller.marshallToJSON(BaseJSONMarshaller.java:103) 
    at com.sun.jersey.json.impl.provider.entity.JSONRootElementProvider.writeTo(JSONRootElementProvider.java:136) 
    at com.sun.jersey.core.provider.jaxb.AbstractRootElementProvider.writeTo(AbstractRootElementProvider.java:157) 
    ... 23 more 
Caused by: javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context. 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:250) 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.reportError(XMLSerializer.java:265) 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:657) 
    at com.sun.xml.bind.v2.runtime.property.SingleElementNodeProperty.serializeBody(SingleElementNodeProperty.java:156) 
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:344) 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:597) 
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:328) 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:498) 
    at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:320) 
    ... 27 more 
Caused by: javax.xml.bind.JAXBException: class Department nor any of its super class is known to this context. 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getBeanInfo(JAXBContextImpl.java:611) 
    at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsXsiType(XMLSerializer.java:652) 
    ... 33 more 
+5

bạn nên chấp nhận câu trả lời được cung cấp vì nó hoạt động tốt. – Daniel

+0

@Shanaka chấp nhận một trong những câu trả lời được cung cấp, #Bogdan câu trả lời là khá tốt. Chọn câu trả lời hay nhất và giúp người khác chọn một cách khôn ngoan – Jeevanantham

Trả lời

49

JAX-RS triển khai tự động hỗ trợ marshalling/unmarshalling các lớp dựa trên chú thích JAXB có thể phát hiện, nhưng vì tải trọng của bạn được khai báo là Object, tôi nghĩ rằng tạo JAXBContext nhớ lớp Department và khi đó là thời gian để marshall nó nó không biết làm thế nào.

Một sửa chữa nhanh chóng và bẩn sẽ có thêm một chú thích XmlSeeAlso đến lớp trả lời của bạn:

@XmlRootElement 
@XmlSeeAlso({Department.class}) 
public class Response implements Serializable { 
    .... 

hoặc một cái gì đó phức tạp hơn một chút sẽ là "làm giàu" bối cảnh JAXB cho lớp Response bằng cách sử dụng một ContextResolver:

import javax.ws.rs.Produces; 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.ContextResolver; 
import javax.ws.rs.ext.Provider; 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 

@Provider 
@Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) 
public class ResponseResolver implements ContextResolver<JAXBContext> { 
    private JAXBContext ctx; 

    public ResponseResolver() { 
     try { 
      this.ctx = JAXBContext.newInstance(

         Response.class, 
         Department.class 

        ); 
     } catch (JAXBException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 

    public JAXBContext getContext(Class<?> type) { 
     return (type.equals(Response.class) ? ctx : null); 
    } 
} 
+1

Tôi có danh sách các đối tượng trong các đối tượng. Được giải quyết bằng thẻ '@ XmlSeeAlso'. Cảm tạ! – Daniel

+1

không hoạt động cho tôi: ( – Anas

+0

Khi tôi sử dụng chú thích XmlSeeAlso, nó thêm thông tin này vào nút: xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi: type = "my_class" –

5

Ngoại lệ này có thể được giải quyết bằng cách chỉ định đường dẫn Lớp học đầy đủ.

Ví dụ:

nếu bạn là lớp tên là ExceptionDetails.java


Way không đúng đối qua

JAXBContext jaxbContext = JAXBContext.newInstance(ExceptionDetails.class); 

Way Right các đối số qua

JAXBContext jaxbContext = JAXBContext.newInstance(com.tibco.schemas.exception.ExceptionDetails.class); 

Nhiều Cảm ơn, Partha

+7

Chắc chắn chỉ định gói sẽ chỉ tạo ra sự khác biệt nếu bạn có hai phiên bản ExceptionDetails khác nhau trong các gói khác nhau và câu lệnh nhập bằng cách sử dụng phiên bản "khác" ? – DarthPablo

2

Tôi có cùng một vấn đề và tôi giải quyết nó bằng cách bổ sung thêm gói để khám phá đến Jaxb2marshaller. Đối với mùa xuân sẽ được xác định một bean như thế này:

@Bean 
    public Jaxb2Marshaller marshaller() { 
     Jaxb2Marshaller marshaller = new Jaxb2Marshaller(); 
     String[] packagesToScan= {"<packcge which contain the department class>"}; 
     marshaller.setPackagesToScan(packagesToScan); 
     return marshaller; 
    } 

Bằng cách này nếu tất cả các request và response lớp học của bạn đang ở trong cùng một gói bạn không cần phải thể hiện cụ thể các lớp trên JAXBcontext

0

tôi đã một vấn đề tương tự khi sử dụng triển khai tham chiếu JAXB và JBoss AS 7.1. Tôi đã có thể viết một bài kiểm tra tích hợp xác nhận JAXB làm việc bên ngoài môi trường JBoss (cho thấy vấn đề có thể là trình nạp lớp trong JBoss).

Đây là mã đó đã đưa ra các lỗi (ví dụ: không làm việc):

private static final JAXBContext JC; 

static { 
    try { 
     JC = JAXBContext.newInstance("org.foo.bar"); 
    } catch (Exception exp) { 
     throw new RuntimeException(exp); 
    } 
} 

và đây là đoạn code mà làm việc (ValueSet là một trong những lớp marshaled từ XML của tôi).

private static final JAXBContext JC; 

static { 
    try { 
     ClassLoader classLoader = ValueSet.class.getClassLoader(); 
     JC = JAXBContext.newInstance("org.foo.bar", classLoader); 
    } catch (Exception exp) { 
     throw new RuntimeException(exp); 
    } 
} 

Trong một số trường hợp, tôi không nhận được Class hoặc bất kỳ lớp siêu nào trong ngữ cảnh này. Trong các trường hợp khác, tôi cũng có ngoại lệ là org.foo.bar.ValueSet không thể chuyển sang org.foo.bar.ValueSet (tương tự như vấn đề được mô tả ở đây: ClassCastException when casting to the same class).