2012-12-05 98 views
0

我想在我的石英調度器頂部創建一個休息api服務器。我希望能夠將org.quartz.Trigger和org.quartz.JobDetail對象作爲JSON返回。問題是我無法將@XmlRootElement添加到這些類中,而無需重新編譯jar,這會導致未來升級等問題。我已經測試並能夠在添加@XmlRootElement時序列化類的列表,但是當我嘗試返回一個List我得到錯誤「Java類java.util.ArrayList的消息主體編寫器,Java類型java.util.List和MIME媒體類型application/json未找到」。我曾嘗試添加一個自定義MessageBodyWriter,但似乎並沒有解決問題。有沒有辦法將石英類編組爲JSON,而無需修改石英代碼來添加@XmlRootElement。我在一個嵌入式Web服務器中使用jetty btw。澤西JSON序列化與外部類

@Path("/jobs") 
public class JobsResource { 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public List<Trigger> listScheduledJobs() throws SchedulerException { 
     return TaskEngine.getInstance().listScheduledJobs(); 
    } 

} 

Web服務器配置

public class TaskEngineWebServer { 

    private static final Logger logger = Logger.getLogger(TaskEngineWebServer.class.getName()); 

    private Server server; 

    public TaskEngineWebServer() { 
     this(8585); 
    } 

    public TaskEngineWebServer(Integer port) { 
     server = new Server(port); 

     logger.info("Configuring rest service to start at url /r"); 
     ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.NO_SECURITY); 
     //handler.getInitParams().put("com.sun.jersey.api.json.POJOMappingFeature", "true"); 
     PackagesResourceConfig packagesResourceConfig = new PackagesResourceConfig("com.hp.vf.scheduler.server.rest"); 

     ServletContainer servletContainer = new ServletContainer(packagesResourceConfig); 
     handler.addServlet(new ServletHolder(servletContainer), "/r/*"); 

     server.setHandler(handler); 
     logger.info("Done configuring rest service"); 
    } 

    public void start() throws Exception { 
     server.start(); 
    } 

    public void stop() throws Exception { 
     server.stop(); 
    } 

    public boolean isStarted() { 
     return server.isStarted(); 
    } 

    public boolean isStopped() { 
     return server.isStopped(); 
    } 
} 

回答

1

我終於想出了一個乾淨的解決方案,它涉及到創建我自己的MediaBodyWriter類並將其添加爲提供程序。你必須確保你沒有使用jersey-bundle jar,因爲默認jaxb to json提供者會覆蓋你的。

罐需要

球衣核 新澤西州的servlet 球衣服務器

傑克遜的註解 傑克遜,數據綁定 傑克遜核心

我在網上找到了這個MediaWriter例如地方。對不起,沒有網址,但感謝誰寫的。

@Provider 
@Produces({ MediaType.APPLICATION_JSON }) 
public class JacksonWriter implements MessageBodyWriter<Object> { 
    private static final ObjectMapper MAPPER = new ObjectMapper(); 

    @Override 
    public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) { 
     return true; 
    } 

    @Override 
    public long getSize(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { 
     return -1; 
    } 

    @Override 
    public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, 
      OutputStream entityStream) { 
     try { 
      MAPPER.writeValue(entityStream, value); 
     } catch (IOException ex) { 
      throw new RuntimeException(ex); 
     } 
    } 
} 

當它加載時,您會看到一條日誌消息,表示您的提供程序已加載。

這給我的JSON輸出我期待,因爲它不依賴於JAXB註解,而只使用對象映射器/反射。可能效率較低,但對我而言並不重要。

1

我不認爲你可以直接返回一個列表作爲JSON。你需要有一個包含這個列表的包裝類。對於例如,嘗試這樣的事情

@XmlRootElement 
@XmlAccessorType(XmlAccessType.FIELD) 
public class TriggerWrapper{ 

    private List<Triggers> triggers; 

    public List<Triggers> getTriggers(){ 
    if(triggers==null){ 
    triggers = new ArrayList<Triggers>(); 
    } 
    return triggers; 
    } 
} 

然後在你休息服務類:

@Path("/jobs") 
public class JobsResource { 

    @GET 
    @Produces(MediaType.APPLICATION_JSON) 
    public TriggerWrapper listScheduledJobs() throws SchedulerException { 
     TriggerWrapper response = new TriggerWrapper(); 
     List<Triggers> triggers = TaskEngine.getInstance().listScheduledJobs(); 
     response.getTriggers.addAll(triggers); 
     return response; 
    } 

} 

您的JSON會是這樣的:

​​

而且ofcourse如果你願意,你可以刪除根據json的元素標籤,可配置在澤西島上。

+0

我去了你昨晚寫了這個問題後,使用相同的路徑,但遇到了一個問題,在觸發類的子接口。觸發器是一個接口,它包含JobKey等的子接口。我開始爲這些類創建@XmlJavaAdapters,但希望檢查答案。你提到有一種方法可以在澤西島配置它,但我不知道如何做到這一點。你能給我一個指針嗎?我嘗試了//handler.getInitParams().put("com.sun.jersey.api.json.POJOMappingFeature「,」true「);配置但它沒有工作。 –

+0

有沒有更簡單的方法來完成這項任務?我真的不喜歡爲我所有的類編寫XmlJavaAdapters的想法。 –