Java RESTful Webservice - FileNotFound - java

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.

Related

Wicket REST functionality works on Jetty but not Tomcat

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.

Getting null error when running a simple JAX-RS app on Websphere Application Server 7

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

CORS support for a Jersey app with WADL

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.

RESTful Web Service eclipse

I followed a very nice tutorial and it works smoothly for the GET http method, but for some reason when I try to access the POST or PUT methods the server returns:
HTTP Status 405 - Method Not Allowed
So this is what I did in the tutorial,
I created a new dynamic web project
I imported the jersey RESTful implementation
I created a new java class and set some jersey annotations
I edited the web.xml file for it to create a servlet on start up with some Jersey set up and point it to my Java class mapping it.
That's it, I ran the app on a tomcat 6 app server.
So when I follow the path of my class and I hence a #GET method it works smoothly but when i try to replace the #GET annotation with #POST it return the error above.
The 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"
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_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>RESTfulTest</display-name>
<servlet>
<servlet-name>NAME</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>com.RESTful.Test</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>NAME</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
My Java class with the jersey annotations:
package com.RESTful.Test;
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;
#Path("/resttest")
public class Test {
//this WORKS!
#GET
#Produces(MediaType.TEXT_PLAIN)
public String getTestString()
{
return "Hello this is a test post";
}
//this returns the error
#POST
#Produces(MediaType.TEXT_PLAIN)
public String getTestString2()
{
return "Hello this is a test post";
}
//this returns the error
#PUT
#Path("{param1}")
#Produces(MediaType.TEXT_PLAIN)
public String getTstWithInput(#PathParam("/param1")
String param)
{
return "hello "+param;
}
//this returns the error
#PUT
#Path(value="/putTest")
#Produces(MediaType.TEXT_PLAIN)
public String getTstWithInput2(#PathParam("/param1")
String param)
{
return "hello "+param;
}
}
Please note that I have tried documenting all but the method I'm testing with the same results. I know I can't run some of them at the same time, they are all just tests.
I'm calling the REST resources from URL:
"http://localhost/RESTfulTest/rest/resttest/"
"http://localhost/RESTfulTest/rest/resttest/myname"
"http://localhost/RESTfulTest/rest/resttest/putTest"
Make sure the rest resources are called properly. Curl can be a hepful tool for testing
curl -XPUT http://localhost/RESTfulTest/rest/resttest/putTest
Try like this
return Response.status(200).entity("Sample Response").type(MediaType.TEXT_PLAIN).build();
More Details :
http://jersey.java.net/nonav/documentation/latest/user-guide.html

How to remove .py from urls for pyservlet using jython

I'm looking at the jython servlet tutorial and have got everything working. How do I make the url be
localhost:8080/jythondemo/JythonServlet1
instead of
localhost:8080/jythondemo/JythonServlet1.py
http://seanmcgrath.blogspot.com/JythonWebAppTutorialPart1.html
Here is the relevant part from web.xml
<web-app>
<servlet>
<servlet-name>ServletTest</servlet-name>
<servlet-class>ServletTest</servlet-class>
</servlet>
<servlet>
<servlet-name>PyServlet</servlet-name>
<servlet-class>org.python.util.PyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletTest</servlet-name>
<url-pattern>/ServletTest</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I've also tried with
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
It seems with the above changes pyservlet is getting the url JythonServlet1 but it does not know what to do with it. Here is the error message:
javax.servlet.ServletException: I can't guess the name of the class from /.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/testjython3/JythonServlet1
org.python.util.PyServlet.createInstance(PyServlet.java:202)
org.python.util.PyServlet.loadServlet(PyServlet.java:188)
org.python.util.PyServlet.getServlet(PyServlet.java:178)
org.python.util.PyServlet.service(PyServlet.java:155)
As noted by #Jigar there's a restriction in the actual Jython Servlet code. However, you may get around that issue by creating a simple URL translator. It consists in a Servlet that internally forwards the request to the Py Servlet.
Use the following code for web.xml:
<web-app>
<servlet>
<servlet-name>AliasServlet</servlet-name>
<servlet-class>juanal.AliasServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>PyServlet</servlet-name>
<servlet-class>org.python.util.PyServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AliasServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>PyServlet</servlet-name>
<url-pattern>*.py</url-pattern>
</servlet-mapping>
</web-app>
Create a new class, say, juanal.AliasServlet, with the following content:
package juanal;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AliasServlet extends HttpServlet
{
#Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
String URI = request.getRequestURI();
String newURI = URI + ".py";
getServletConfig().getServletContext().getRequestDispatcher(newURI).forward(request, response);
}
}
So, for a URL like this: localhost:8080/jythondemo/JythonServlet1, it will internally forward the request to JythonServlet1.py
Try this
<url-pattern>/*</url-pattern>
After that every request will be served by PyServlet
It looks like the problem is inherent to PyServlet.java. PyServlet uses regular expressions to find the name of the Python class to load based on the path of the request. The regular expression used is defined as follows (line 245 in my copy of the source):
private static final Pattern FIND_NAME = Pattern.compile("([^/]+)\\.py$");
Unfortunately, this regular expression will break if the input URL path doesn't contain a ".py" extension - this raises the error that you saw. From line 200:
Matcher m = FIND_NAME.matcher(file.getName());
if (!m.find()) {
throw new ServletException("I can't guess the name of the class from "
+ file.getAbsolutePath());
}
Since FIND_NAME is defined as private and final, I don't see a good way to override this behavior by just subclassing PyServlet - I think you'll have to make a copy of PyServlet and redefine this behavior in a fresh class.
I'm new to python. But if you have Apache, you could rewrite all .py URLs!
Just for the record: #Juanal AliasServlet trick works nicely.
I just had to use request.getServletPath() instead of getRequestURI().
(working with Eclipse)

Categories

Resources