I have created a Wicket application that has recently been upgraded with the wicket REST functionality. When developing it and running through Jetty, I am able to post messages to the REST service correctly. However when it is deployed to tomcat, going to the REST URL gives a 404 error and a 'requested resource is not available' response.
Pom entries:
wicketstuff-annotation, wicketstuff-restannotations, wicketstuff-restannotations-json (all jar/compile, version identical to wicket version 6.24.0)
Code in the rest class
public class Webhook extends AbstractRestResource<JsonWebSerialDeserial> {
#MethodMapping(value="/notification", httpMethod=HttpMethod.POST, consumes= RestMimeTypes.APPLICATION_JSON, produces = RestMimeTypes.TEXT_PLAIN)
public String notification( #RequestBody Notification data ) {
// do some things
return "received successfully";
}
#Override
public String getMountPath() {
return "/emailcampaign/webhook";
}
}
The REST class is initialized in WicketApplication:
public void init() {
final Webhook hook = new Webhook();
mountResource( hook.getMountPath(), new ResourceReference( hook.getClass().getSimpleName() ) {
private static final long serialVersionUID = 1L;
public IResource getResource() {
return hook;
}
});
}
The tomcat localhost_access_logs have this:
`XX.XX.XX.XX - - [01/Feb/2018:06:46:10 +0000] "POST /emailcampaign/webhook/notification HTTP/1.1" 404 1041
The system starts up correctly, so I don't appear to be missing any jar files on deployment, so I'm at a loss. Can anyone help please?
Tomcat 7.0.67, Jetty 7.6.3, Wicket 6.24, Spring 4.1.4
Edit: This is the content of the web.xml:
<?xml version="1.0" encoding="ISO-8859-1"?>
<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>system-ui</display-name>
<context-param>
<param-name>configuration</param-name>
<param-value>deployment</param-value>
</context-param>
<filter>
<filter-name>wicket.system-ui</filter-name>
<filter-class>org.apache.wicket.protocol.http.WicketFilter</filter-class>
<init-param>
<param-name>applicationClassName</param-name>
<param-value>com.sw.system.ui.WicketApplication</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>wicket.system-ui</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
....aaand this was down to a rookie oversight.
On my development machine, the path to the application on jetty was http://localhost:8080. On the deployment machine, it's http://[server_name]/theapp. So I set the Client REST URL to point to http://[server_name]/theapp/emailcampaign/webhook/notification (ie add the theapp subpath) and it worked!
Doh but hopefully it helps someone else out.
Related
i have a problem with writing a REST API. I wrote a little client to test the service, but i keep getting exceptions and errors.
Here's some of my code:
The deployment descriptor:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>com.boss.rest.example</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>ConfigServlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ConfigServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
</web-app>
The client code:
public static void main(String[] args)
try {
String url_str = "http://localhost:8080/com.boss.rest.example/api/getRandomRamp";
URL url = new URL(url_str);
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setRequestProperty("Accept", "application/json");
System.out.println("Response code: " + c.getResponseCode());
System.out.println(c.getInputStream().toString());
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
And the servlet code:
#Path("/api")
public class ConfigServlet {
#Context
UriInfo uriInfo;
#GET
#Path("/getRandomRamp")
#Produces(MediaType.APPLICATION_JSON)
public Response getRandomRamp() {
String s = ">> This is just a random string, no real interaction with the backend available yet! <<";
System.out.println("Service SysOut: " + s);
return Response.status(200).entity(s).build();
}
}
With this code i get a FileNotFoundException for the given URL. Can anyone help? Thanks a lot!
You seem to have an issue with your api path. You have defined root path("/api/") at 2 places. Once in your deployment descriptor and the other in your Servlet. Change one of them to ("/")
I believe its the url which is causing the issue. seems like the context you are using contains the periods which is not a valid context name. trying changing the url to the application name(context) and it should work.
so
replace
"http://localhost:8080/com.boss.rest.example/api/getRandomRamp"
with
"http://localhost:8080/contextname/api/getRandomRamp"
How you deploy your application? Usually you have to do it to some server like Tomcat - and this server deploys it by certain name.
Also, display-name is Display Name, nothing else. Especially not deployment location.
I am pretty new to Jersey REST. I follow the tutorial http://javapapers.com/java/restful-web-services-with-java-jax-rs-using-jersey/. It works well locally on Tomcat 7. But when I deploy it into Openshift, I simply got 404 not found.
This is my web.xml
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.market.ws</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
And this is my resource
#Path("/api")
public class TicketsResource {
// Allows to insert contextual objects into the class,
// e.g. ServletContext, Request, Response, UriInfo
#Context
UriInfo uriInfo;
#Context
Request request;
// Return the list of todos to the user in the browser
// With the browser you can only issue HTTP GET requests\
#Path("/query")
#GET
#Produces(MediaType.TEXT_XML)
public List<Ticket> getTicketsBrowser() {
List<Ticket> tickets = new ArrayList<Ticket>();
tickets.addAll(TicketDao.instance.getModel().values());
return tickets;
}
// Return the list of todos for applications
// Default for browser GET
#Path("/query")
#GET
#Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public List<Ticket> getTickets() {
List<Ticket> tickets = new ArrayList<Ticket>();
try {
tickets.addAll(TicketDao.instance.getModel().values());
} catch(Exception e) {
e.printStackTrace();
}
return tickets;
}
}
I use http://localhost:8080/myproject/api/query and it works fine. But in openshift I use http://market-domain.rhcloud.com/myproject/api/query or http://market-domain.rhcloud.com/api/query it doesn't work. I tried to deploy using Tomcat 7 or JBoss AS 7 but they both gave me the same error. I didn't find any error in log file. Looks like the resource simply doesn't exist. I am wondering is my url wrong or anything else? I should be able to query this rest ws immediately after deploy, right? Thanks in advance.
Finally I found out it's my war file problem. I used maven build for 3 projects but it doesn't work. Then I just use export war in Eclipse to generate war file. Then resource can be found after deploying.
I have no compilation errors and my app launches fine on my testing server. However, I get an error when trying a GET request:
[1/2/14 10:23:13:248 EST] 00000022 RequestProces I org.apache.wink.server.internal.RequestProcessor logException The following error occurred during the invocation of the handlers chain: WebApplicationException (404 - Not Found) with message 'null' while processing GET request sent to http://localhost:9081/IDMWorkflowServices/resources/workflow
Here is my web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.5" 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">
<display-name>IDMWorkflowServices</display-name>
<servlet>
<description>
JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>com.psg.itim.workflow.WorkflowResourceApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>
/resources/*</url-pattern>
</servlet-mapping>
</web-app>
Here is WorkflowResource:
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
// The Java class will be hosted at the URI path "/workflow"
#Path("/workflow")
public class WorkflowResource {
#GET
#Produces("text/plain")
public String getClichedMessage() {
// Return some cliched textual content
return "Hello World";
}
}
Here is WorflowResourceApplication:
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;
public class WorkflowResourceApplication extends Application{
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(WorkflowResource.class);
return classes;
}
}
If it's not painfully obvious, this is my first attempt using JAX-RS. I'm not exactly sure what I do or do not need from the above code to get this to work. It seems simple, but when I go to this url
http://localhost:9081/IDMWorkflowServices/resources/workflow
the 404 happens. Any ideas of what I am doing wrong?
Resolved! The only thing that was wrong was this line:
<param-name>javax.ws.rs.core.Application</param-name>
I changed it to:
<param-name>javax.ws.rs.Application</param-name>
I assumed it should have been the same Class I was calling from WorflowResourceApplication.java, but this was not the case. Everything works fine now. Apparently the application recognized the class error as a client side issue and registered a 404.
The first step to debug this would be to see if you have the correct port. So do this
- Try accessing just - http: //localhost:9081 . see if you get to default page or blank page or hello page if there is default index.jsp. If you get 404 then that means that you serever is running but your port number is incorrect.
If you are unsure what your port settings are(If I am correct then default port should be 9080) then follow this documentation - http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=%2Fcom.ibm.websphere.migration.nd.doc%2Finfo%2Fae%2Fae%2Frmig_portnumber.html
I have a Java Application in Eclipse. Using Jersey, it successfully creates a webpage locally (localhost).
The problem is I have a javascript on another server trying to access that webpage and it throws a CORS error.
Is there any built-in CORS support for Jersey/WADL applications?
I've tried creating a Jersey filter that supports CORS - following these instructions. No luck. :( I'm looking into this, but am unsure if it is the right choice for what I want to do.
Essentially, my header is currently this:
But I want it to look something like this:
Thanks all!
EDIT:
As per jgm's suggestion, I have created a filter (called CORSFilter) and added the requesite dependencies. Am I registering the filter correctly in the web.xml file?
<?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" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 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>createJPA</display-name>
<servlet>
<servlet-name>Jersey Root REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Root REST Service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>CORSFilter</filter-name>
<filter-class>model.producer.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORSFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
Here is a simple CORS filter for jersey, adapted from the Weald Technology utilities:
import com.google.inject.Inject;
import com.sun.jersey.spi.container.ContainerRequest;
import com.sun.jersey.spi.container.ContainerResponse;
import com.sun.jersey.spi.container.ContainerResponseFilter;
import com.wealdtech.jersey.CORSConfiguration;
/**
* Filter to handle cross-origin resource sharing.
*/
public class CORSFilter implements ContainerResponseFilter
{
private static final String ACAOHEADER = "Access-Control-Allow-Origin";
private static final String ACRHHEADER = "Access-Control-Request-Headers";
private static final String ACAHHEADER = "Access-Control-Allow-Headers";
private static final String ACAMHEADER = "Access-Control-Allow-Methods";
private static final String ACACHEADER = "Access-Control-Allow-Credentials";
private final transient CORSConfiguration configuration;
#Inject
public CORSFilter(final CORSConfiguration configuration)
{
this.configuration = configuration;
}
#Override
public ContainerResponse filter(final ContainerRequest request, final ContainerResponse response)
{
response.getHttpHeaders().add(ACAOHEADER, this.configuration.getOrigin());
final String requestHeaders = request.getHeaderValue(ACRHHEADER);
response.getHttpHeaders().add(ACAHHEADER, requestHeaders);
response.getHttpHeaders().add(ACAMHEADER, this.configuration.getAllowedMethods());
response.getHttpHeaders().add(ACACHEADER, this.configuration.allowCredentials());
return response;
}
}
For the configuration you can either use the existing configuration setup or incorporate it in to your own system. Note that this uses Google Guice to inject the configuration, if you aren't using Guice you'll need to do this manually.
I create guice servlet like this:
public class GuiceApplicationServlet extends AbstractApplicationServlet {
protected Provider<Application> applicationProvider;
public GuiceApplicationServlet() {
System.out.println("TTest");
}
#Inject
public GuiceApplicationServlet(Provider<Application> applicationProvider) {
super();
this.applicationProvider = applicationProvider;
System.out.println("Test");
}
#Override
protected Class<? extends Application> getApplicationClass()
throws ClassNotFoundException {
return Application.class;
}
#Override
protected Application getNewApplication(HttpServletRequest request)
throws ServletException {
return applicationProvider.get();
}
}
web.xml:
<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>
<listener>
<listener-class>pl.koziolekweb.vaadin.guice.servlet.VaadinGuiceConfiguration</listener-class>
</listener>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>pl.koziolekweb.vaadin.guice.servlet.GuiceApplicationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The problem is that when I run jetty then Guice create instance of servlet (print "Test" in console) but when I try to run application in browser i get NPE and in console "TTest" appear.
So jetty create another instance of servlet that is not managed by guice.
Question is how to configure jetty to use only guice?
You have to create a guice servlet module which extends com.google.inject.servlet.ServletModule (let's call it FooModule). You define there your bindings and paths to servlets by overriding configureServlets() method.
Then you must create context listener by extending com.google.inject.servlet.GuiceServletContextListener (let's call it BarContextListener). There you must implement getInjector() method, with something like that:
protected Injector getInjector() {
Injector injector = Guice.createInjector(new FooModule());
return injector;
}
Then you remove all servlet mappings from your web.xml, and then put filter:
<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>
and context listener You created:
<listener>
<listener-class>path.to.package.of.context.listener.BarContextListener</listener-class>
</listener>
By this all Your servlets are managed by Guice and enable dependency injection in server side of Your application. It works for me in Tomcat so it should also work on Jetty. Don't forget to include guice-servlet-<version>.jar into your classpath. I didn't use it with Vaadin, but I guess my answer helped You little bit.
Because Guice should create all your Servlet instances, you have to remove the servlet and servlet-mapping entries from your web.xml file.
I have written a blog post on the subject, I'm sure it would be most helpful :
Vaadin + GAE + Guice-Servlet - TUTORIAL