简体   繁体   中英

jersey-test-framework grizzly returns 404 not found error

I want to implement JUnit tests for Jersey REST/Json in to my application.

My problem is that I get a 404 not found back from Grizzly. But the path is correct and tests with Curl over the normal Webcontainer are working.

I'm using GWTP (without maven). I'm implementing the libraries by hand Properties -> Java Build Path. I'm using following Versions:

  • Eclipse Indigo (on 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
  • grizzly-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
  • servlet-api-2.5.jar
  • junit-4.9.jar (also tested with 4.10.jar)

All libraries are included according to the Jersey documentation: http://jersey.java.net/nonav/documentation/latest/user-guide.html - Chapter 7.5 Running tests outside Maven.

The stacktrace is following:

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...

My classes look as followed:

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>

Testing with Curl and following command works when running the application as a Web Appliction:

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\" }"

I have even tried to sniff the loopback interface with RawCap.exe. I see following in the PCAP file:

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

This looks to me like the JSON string is submitted to the URL but no classes can be found.

I'm stuck here a little. I must be doing something wrong with the context path but I can't figure out what to do and how to set it.

Thanks for your help, Chris

When running the app as a web application, it gets exposed at /api/ URL based on the web.xml. Neither Grizzly nor lightweight HTTP server recognize web.xml, so they expose jersey at the container root.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM