読者です 読者をやめる 読者になる 読者になる

WildFly8.2 が出てるので Jersey 載せてみた

WildFly-8.2.0.Final が何日か前に出てました。
WildFly Homepage · WildFly

WildFly-8.1.0.Final の JAX-RS(RESTEasy) で JSONP を返そうとして上手く動かず。。 ※上手く動くサンプルどっか知りません?

Jersey で JSONP は結構ブログとかに書かれているんですが、RESTEasy(WildFly) で JSONP はあまり情報が無く、サポートされる前の情報がちらほらとある感じでした。*1
java - How enable JSONP in RESTEasy? - Stack Overflow

ついカッとなって Jersey で試してみました!

とりあえず RESTEasy で動かしてから Jersey に載せかえます。
サンプルは、Text と JSON 返す JAX-RS のコード片です。Xtend では無く Java で書いてるので伝わりますよね。

@Path("api")
public class MyApplication extends Application {
}

@RequestScoped
@Path("hello")
public class HelloWorldResource {
  @GET
  public Dto helloworld(@QueryParam("name") String name) {
    return "Hello " + name;
  }
}

@Data @AllArgsConstructor
public class Dto {
  private int id;
  private String name;
}

@RequestScoped
@Path("json")
public class JsonResource {
  @GET
  @Produces({ "application/json" })
  public Dto helloworld(@QueryParam("name") String name) {
    return new Dto(1, name);
  }
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>jaxrstest</display-name> 
  <servlet>
    <servlet-name>resteasy</servlet-name>
    <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>resteasy</servlet-name>
    <url-pattern>/api/*</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>resteasy.scan</param-name>
    <param-value>true</param-value>
  </context-param> 
  <context-param>
    <param-name>resteasy.servlet.mapping.prefix</param-name>
    <param-value>/api</param-value>
  </context-param> 
</web-app>

これで /api/hello?name=abc で「Hello abc」が /api/json?name=abc で「{"id":1,"name":"abc"}」が返ってきます。

こっから Jersey を載せてきます。
今回は com.sun.jersey:jersey-bundle と com.sun.jersey:jersey-json の 1.18.2 で試しました。
web.xml を Jersey 用にします。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
  <display-name>jaxrstest</display-name>
  <servlet>
    <servlet-name>jersey-serlvet</servlet-name>
    <servlet-class>
        com.sun.jersey.spi.container.servlet.ServletContainer
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
      <servlet-name>jersey-serlvet</servlet-name>
      <url-pattern>/api/*</url-pattern>
  </servlet-mapping>
</web-app>

これだけでさっきのコードが Jersey で一応動きます。

wildfly のログに jersey とか出てますね!

一応と付けたのは、text で返す方は動きますが、json 返す方は動きません。
json の方にアクセスするとこんな例外が返ります。

Context Path:/jaxrstest
Servlet Path:/api
Path Info:/json
Query String:name=abc

Stack Trace
org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.ws.rs.ext.Providers
org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy.invoke(ContextParameterInjector.java:53)
com.sun.proxy.$Proxy49.getContextResolver(Unknown Source)
org.codehaus.jackson.jaxrs.JacksonJsonProvider.locateMapper(JacksonJsonProvider.java:633)
org.codehaus.jackson.jaxrs.JacksonJsonProvider.writeTo(JacksonJsonProvider.java:500)
org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider$Proxy$_$$_WeldClientProxy.writeTo(Unknown Source)
com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:302)
com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:558)
com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:733)
javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61)
io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45)
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:63)
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58)
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70)
io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:261)
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:247)
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:76)
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:166)
io.undertow.server.Connectors.executeRootHandler(Connectors.java:197)
io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:759)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)

RESTEasy から ContextResolver 取ろうとしてこけてるようです。

ここで WildFly から jaxrs のモジュールを取っ払います。
WEB-INFjboss-deployment-structure.xml を置きます。

<?xml version='1.0' encoding='UTF-8'?>
<jboss-deployment-structure> 
  <deployment>
    <exclude-subsystems>
      <subsystem name="jaxrs" />
    </exclude-subsystems>
  </deployment>
</jboss-deployment-structure>

これで RESTEasy を取っ払えます。再度デプロイすると JSON の方もちゃんと動きます。

で最後に JSON -> JSONP にします。*2

@RequestScoped
@Path("json")
public class JsonResource {
  @GET
  @Produces({ "application/javascript" })
  public JSONWithPadding helloworld(@QueryParam("name") String name) {
    return new JSONWithPadding(new Dto(1, name));
  }
}

application/javascript にすると JSONP 強制らしいです。
/api/json?name=abc 叩くと「callback({"id":1,"name":"abc"})」となりました。

というわけで、RESTEasy 取っ払うと WildFly でも Jersey それなりに動きそうですね! RESTEasy で JSONP はもうちょい調べてみます。。

*1:自前で Filter とか

*2:今回は強制的に JSONP