Jersey REST/Json の JUnit テストをアプリケーションに実装したいと考えています。
私の問題は、Grizzly から 404 not found が返されることです。しかし、パスは正しく、通常の Webcontainer で Curl を使用したテストは機能しています。
私はGWTPを使用しています(mavenなし)。プロパティ - > Javaビルドパスでライブラリを手動で実装しています。私は次のバージョンを使用しています:
- Eclipse インディゴ (Windows 7 上)
- asm-3.3.1.jar
- jersey-client-1.12.jar
- jersey-core-1.12.jar
- jersey-json-1.12.jar
- jersey-server-1.12.jar
- jersey-servlet-1.12.jar
- jersey-test-framework-core-1.12.jar
- jersey-test-framework-grizzly-1.12.jar
- grizzly-framework-1.9.45.jar
- グリズリー-http-1.9.45.jar
- grizzly-http-servlet-1.9.45.jar
- grizzly-portunif-1.9.45.jar
- grizzly-rcm-1.9.45.jar
- grizzly-servlet-webserver-1.9.45.jar
- grizzly-utils-1.9.45.jar
- サーブレット-api-2.5.jar
- junit-4.9.jar (4.10.jar でもテスト済み)
すべてのライブラリは、Jersey のドキュメントに従って含まれています: http://jersey.java.net/nonav/documentation/latest/user-guide.html - Chapter 7.5 Running tests outside Maven.
スタックトレースは次のとおりです。
INFO: GRIZZLY0001: Starting Grizzly Framework 1.9.45 - 01.07.12 12:11
01.07.2012 10:11:20 com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
com.acolsolutions.loyaltycard.resources
01.07.2012 10:11:20 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class com.acolsolutions.loyaltycard.resources.HelloResource
class com.acolsolutions.loyaltycard.resources.CardResource
01.07.2012 10:11:20 com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
01.07.2012 10:11:20 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.12 02/15/2012 04:51 PM'
com.sun.jersey.api.client.UniformInterfaceException: POST http://localhost:9998 /api/cards returned a response status of 404 Not Found
at com.sun.jersey.api.client.WebResource.voidHandle(WebResource.java:707)
at com.sun.jersey.api.client.WebResource.access$400(WebResource.java:74)
at com.sun.jersey.api.client.WebResource$Builder.post(WebResource.java:553)
at com.acolsolutions.loyaltycard.junit.CardResourceTests.testCreate(CardResourceTests.java:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:69)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:48)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:292)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
01.07.2012 10:11:21 com.sun.jersey.test.framework.spi.container.grizzly.web.GrizzlyWebTestContainerFactory$GrizzlyWebTestContainer stop
INFO: Stopping the Grizzly Web Container...
私のクラスは次のようになります。
CardResourceTests.java:
import static org.junit.Assert.assertFalse;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.google.appengine.tools.development.testing.LocalDatastoreServiceTestConfig;
import com.google.appengine.tools.development.testing.LocalServiceTestHelper;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.test.framework.JerseyTest;
import com.sun.jersey.test.framework.WebAppDescriptor;
import org.codehaus.jettison.json.JSONObject;
public class CardResourceTests extends JerseyTest {
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(
new LocalDatastoreServiceTestConfig());
public CardResourceTests() throws Exception {
super("com.acolsolutions.loyaltycard.resources");
}
/*
@Before
public void setUp() {
helper.setUp();
}
@After
public void tearDown() {
helper.tearDown();
}
*/
@Test
public void testCreate() {
boolean thrown = false;
WebResource webResource = resource();
JSONObject card = new JSONObject();
try {
card.put("id", "1")
.put("name", "Name of Card")
.put("code", "123456")
.put("codeTypeId", "1")
.put("cardProviderName", "The Card Provider")
.put("picturePath", "provider.jpg")
.put("cardProviderUrl", "http://www.provider.com")
.put("creationDate", "Sun Jun 10 08:55:14 UTC 2012")
.put("modificationDate","Sun Jun 10 08:55:14 UTC 2012");
webResource.path("api/cards").type("application/json").post(card);
} catch(Exception e) {
e.printStackTrace();
thrown = true;
}
assertFalse(thrown);
}
}
CardRessource.java:
import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.acolsolutions.loyaltycard.dataobjects.CardDAO;
import com.acolsolutions.loyaltycard.persistence.entities.Card;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.allen_sauer.gwt.log.client.Log;
@Path("/cards")
public class CardResource {
CardDAO dao = new CardDAO();
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response create(Card card) {
Log.debug("Creating card");
Card c = dao.create(card);
if(c.equals(null)) {
return Response.status(400).entity("Create failed!").build();
}
return Response.status(201).entity(c).build();
}
...
}
web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>loyaltycard</display-name>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>loyaltycard.html</welcome-file>
</welcome-file-list>
<!--
The below lines are implementing Jersey (JAX-RS) in to the GWT application.
-->
<servlet>
<servlet-name>Jersey</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
<param-value>com.sun.jersey.api.core.PackagesResourceConfig</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.acolsolutions.loyaltycard.resources</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Jersey</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<!--
This Guice listener hijacks all further filters and servlets. Extra
filters and servlets have to be configured in your
ServletModule#configureServlets() by calling
serve(String).with(Class<? extends HttpServlet>) and
filter(String).through(Class<? extends Filter)
-->
<listener>
<listener-class>com.acolsolutions.loyaltycard.server.guice.GuiceServletConfig</listener-class>
</listener>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
アプリケーションを Web アプリケーションとして実行すると、Curl と次のコマンドを使用したテストが機能します。
curl http://localhost:8888/api/cards -i -X POST -H "Content-Type: application/json" -d "{\"id\": \"1\", \"name\": \"Name of Card\", \"code\": \"123456\", \"codeTypeId\": \"1\", \"cardProviderName\": \"Card Provider\", \"picturePath\": \"provider.jpg\", \"cardProviderUrl\": \"http://www.provider.com\", \"creationDate\": \"Sun Jun 10 08:55:14 UTC 2012\", \"modificationDate\": \"Sun Jun 10 08:55:14 UTC 2012\" }"
私は、RawCap.exe を使用してループバック インターフェイスをスニッフィングしようとさえしました。PCAP ファイルに次のように表示されます。
POST /api/cards HTTP/1.1
Content-Type: application/json
User-Agent: Java/1.7.0
Host: localhost:9998
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 254
{"id":"1","name":"Name of Card","code":"123456","codeTypeId":"1","cardProviderName":"Card Provider","picturePath":"provider.jpg","cardProviderUrl":"http:\/\/www.provider.com","creationDate":"Sun Jun 10 08:55:14 UTC 2012","modificationDate":"Sun Jun 10 08:55:14 UTC 2012"}
HTTP/1.1 404 Not Found
server: grizzly/1.9.45
Content-Type: text/plain; charset=iso-8859-1
Transfer-Encoding: chunked
Date: Sun, 01 Jul 2012 00:02:16 GMT
これは、JSON 文字列が URL に送信されているように見えますが、クラスが見つかりません。
私はここで少し立ち往生しています。コンテキストパスに何か問題があるに違いありませんが、何をすべきか、それを設定する方法がわかりません。
助けてくれてありがとう、クリス