2012-12-05 60 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的想法。 –