I'm currently trying to run a servlet that check a GET value and write the value.
Here my class :
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Servlet extends HttpServlet {
/**
*
*/
public Servlet() {
// TODO Auto-generated constructor stub
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String myValue = request.getParameter("MyValue");
if (myValue != null && !myValue.isEmpty()) {
response.getWriter().write(myValue);
}
}
}
It's quit simple, right ?
I already tried many url to be able to see my result like the following :
- http://localhost:8080/Servlet/servlet/Servlet
- http://localhost:8080/Servlet/servlet/Servlet?MyValue=Test
- http://127.0.0.1:8080/Servlet/servlet/Servlet
- http://127.0.0.1:8080/Servlet/servlet/Servlet?MyValue=Test
Is there something wrong with my code or is it a problem with my eclipse?
Thx
You didn't tell anything about the problem symptoms, but I'll assume that you're getting a HTTP 404 error page on all the attempts, right?
You need to map the servlet on an URL pattern. First, you need to assure that the servlet class is placed in a package (we'll assume com.example in this answer).
If you're still on Java EE 5 (or even J2EE..), register it in the webapp's /WEB-INF/web.xml (Eclipse should have autogenerated one):
<servlet>
<servlet-name>servlet</servlet-name>
<servlet-class>com.example.Servlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet</servlet-name>
<url-pattern>/servlet</url-pattern>
</servlet-mapping>
(the servlet name is basically the instance variable name, there's only one applicationwide; the servlet class is obviously the FQN; the URL pattern the webcontent-relative URL of the servlet)
Or when you're already on the latest Java EE 6, then annotate it with #WebServlet wherein you specify the URL pattern as value:
package com.example;
// ...
#WebServlet("/servlet")
public class Servlet extends HttpServlet {
// ...
}
Either way, it's basically telling that the servlet should listen on webcontent-relative URLs matching /servlet. So, assuming that your web context root path is /Servlet, then this should do:
http://localhost:8080/Servlet/servlet
In the future, it'd be easier if you created the servlet class by New > Servlet instead of New > Class, then this all will be automagically taken into account in the wizard.
See also:
Our Servlets wiki page - contains some Hello World examples - you can get to this page by hovering your mouse a while above the servlets until a black info box shows up and then clicking the info link therein.
You can find your Context Root by right clicking your project in eclipse -> Properties -> Web Project Settings.
Related
I know that there were similar problems already, but non of the solutions worked for me. I checked the directories and I edited my `web.xml file a couple of times but it still does not work.
I am writing a simple servlet in Java running on Tomcat and I am getting the error:
HTTP Status 404 – Not Found
Type Status Report
Message /WorkshopForm/MainWorkshopForm
Description The origin server did not find a current representation
for the target resource or is not willing to disclose that one exists.
My servlet class is:
package workshop;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
#WebServlet(description = "This registration form", urlPatterns = {
"/WorkshopForm" })
public class WorkshopForm {
public class MyServlet extends HttpServlet implements Servlet {
private static final long serialVersionUID = 13425L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String participantName = request.getParameter("participantName");
String participantSurname = request.getParameter("participantSurname");
String participantEmail = request.getParameter("participantEmail");
PrintWriter writer = response.getWriter();
writer.println("Welcome" + participantName + " " + participantSurname + " " + participantEmail);
}
}
}
My web.xml:
Tree in Eclipse:
Is it a problem with the web.xml file? I am thinking that maybe I have some mismatch with names or paths but I tried to solved it already and no idea why it is not working.
The URL pattern /WorkshopForm matches only the exact URL path /WorkshopForm. If you want the servlet to also handle longer paths like /WorkshopForm/MainWorkshopForm, you need to change the URL pattern to /WorkshopForm/*. Then you can call request.getPathInfo() in your servlet code to obtain the variable part of the path.
Another alternative is to use some JAX-RS framework to handle the mapping from URL paths to Java methods that handle individual paths.
I'm a university student, currently developing an Android app for a module. Working on connecting it to a server to perform logins, etc. The department have given us a server to use and instructed us to use Servlets. I would rather do it a Restful manner, seeming as it's an industry standard. Here is the code I have written so far:
import javax.ws.rs.QueryParam;
/**
*
* #author Tom
*/
public class Login {
public boolean doLogin(#QueryParam("email") String email) {
return checkCredentials(email);
}
private boolean checkCredentials(String email){
boolean result = false;
if (email != ""){
try {
result = DBConnection.checkLogin(email);
} catch (Exception e) {
result = false;
}
} else {
result = false;
}
return result;
}
}
I wrote another class, DBConnection, but this seems to work ok (using JDBC to connect to the MySQL database).
The problem I'm having, is that when I run the webserver (using Jetty, and ant is the build tool) and try to access the page on the server through my browser, it just gives me a 503, Servlet not initialised error. I assume this is because I'm not extending the HttpServlet class? Here is some example Servlet code they gave us:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class Product extends HttpServlet
{
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
httpServletResponse.setContentType("text/plain");
PrintWriter out = httpServletResponse.getWriter();
out.println("Hello");
out.close();
}
}
They've given us a file called JettyStart.java, which starts the web server when you run ant:
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHttpContext;
public class JettyStart
{
public static void main(String[] args) throws Exception
{
//A server running at http://localhost:8085 is created
Server server = new Server();
server.addListener(":8085");
ServletHttpContext context = (ServletHttpContext) server.getContext("/");
context.addServlet("/path/to/Login", "package.name.Login");
server.start();
}
}
So how would I go about integrating Servlets into my Restful approach to communicating with the server/database? Or am I doing it all wrong?
I'm not sure if this is an answer, but you may have better luck making your project maven-based and using the jetty-maven-plugin. I have, personally. It's easy to set up if you have an IDE which can produce a simple maven archetype. You just drop the plugin into your pom and run mvn jetty:run from the command line. Wiring up the JAX-RS web services isn't too complicated, you just give them the correct annotations like so:
package com.my.project.services;
// imports here
#Path("/login")
public class Login extends HttpServlet {
#GET
#Produces({"text/html", MediaType.TEXT_HTML})
public String getLoginInfo(#QueryParam("email") String email) {
// ...
}
}
And that should be enough to get them picked up by the jetty servlet container as long as your web.xml is set up properly. If you use a maven webapp archetype this may be done for you, otherwise you'll have to poke around a bit, but if it helps this is what (the relevant parts of) my web.xml looks like in one of my projects:
<web-app>
<servlet>
<servlet-name>rest</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>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.my.project.services</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>rest</servlet-name>
<url-pattern>/myproject/rest/*</url-pattern>
</servlet-mapping>
</web-app>
The mapping here is saying take the servlet-name "rest" and map it to the package com.my.project.services where all my JAX-RS services live, with the #Path value appended to the end (so the login service above would be located at /myproject/rest/login). You can set the mapping paths up any way you want.
edit: should mention my project is also using Jersey. Here's a good guide to setting up a project like this: http://crunchify.com/how-to-build-restful-service-with-java-using-jax-rs-and-jersey/
This question already has answers here:
Servlet returns "HTTP Status 404 The requested resource (/servlet) is not available"
(19 answers)
Closed 1 year ago.
I am writing a Java Servlet, and I am struggling to get a simple HelloWorld example to work properly.
The HelloWorld.java class is:
package crunch;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
I am running Tomcat v7.0, and have already read similar questions, with responses referring to changing the invoker servlet-mapping section in web.xml. This section actually doesn't exist in mine, and when I added it the same problem still occurred.
Try this (if the Java EE V6)
package crunch;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
#WebServlet(name="hello",urlPatterns={"/hello"}) // added this line
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("Hello World");
}
}
now reach the servlet by http://127.0.0.1:8080/yourapp/hello
where 8080 is default Tomcat port, and yourapp is the context name of your applciation
You definitely need to map your servlet onto some URL. If you use Java EE 6 (that means at least Servlet API 3.0) then you can annotate your servlet like
#WebServlet(name="helloServlet", urlPatterns={"/hello"})
public class HelloWorld extends HttpServlet {
//rest of the class
Then you can just go to the localhost:8080/yourApp/hello and the value should be displayed. In case you can't use Servlet 3.0 API than you need to register this servlet into web.xml file like
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>crunch.HelloWorld</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
Writing Java servlets is easy if you use Java EE 7
#WebServlet("/hello-world")
public class HelloWorld extends HttpServlet {
#Override
public void doGet(HttpServletRequest request,
HttpServletResponse response) {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("Hello World");
out.flush();
}
}
Since servlet 3.0
The good news is the deployment descriptor is no longer required!
Read the tutorial for Java Servlets.
this is may be due to the thing that you have created your .jsp or the .html file in the WEB-INF instead of the WebContent folder.
Solution: Just replace the files that are there in the WEB-INF folder to the Webcontent folder and try executing the same - You will get the appropriate output
For those stuck with "The requested resource is not available" in Java EE 7 and dynamic web module 3.x, maybe this could help: the "Create Servlet" wizard in Eclipse (tested in Mars) doesn't create the #Path annotation for the servlet class, but I had to include it to access successfuly to the public methods exposed.
You have to user ../../projectName/Filename.jsp in your action attr. or href
../ = contains current folder simple(demo.project.filename.jsp)
Servlet can only be called with 1 slash forward to your project name..
My problem was in web.xml file. In one <servlet-mapping> there was an error inside <url-pattern>: I forgot to add / before url.
I'm using SimpleCaptcha to secure our contact form. It works well, but only after reloading the page.
The Servlet is nl.captcha.servlet.StickyCaptchaServlet, so it should not change the image after reloads. But when first opening the page the image is just not loaded. However, after reloading everything works fine.
the web.xml
The captcha is served by an application running at /services.
<web-app>
<servlet>
<servlet-name>captcha</servlet-name>
<servlet-class>nl.captcha.servlet.StickyCaptchaServlet<servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>captcha</servlet>
<url-pattern>/captcha.png</url-pattern>
</servlet-mapping>
</web-app>
the html
<img src="/services/captcha.png">
the server
I'm using tomcat-7.0.34 on a Windows 7 64bit machine with Java 1.7.0_07.
the question
Why does the image only show up after a reload? Any ideas?
there are several steps you can follow:
1> modify web.xml add your servlet that extends nl.captcha.servlet.StickyCaptchaServlet class
<servlet>
<description></description>
<display-name>CustomCaptchaServlet</display-name>
<servlet-name>CustomCaptchaServlet</servlet-name>
<servlet-class>org.example.servlets.CustomCaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CustomCaptchaServlet</servlet-name>
<url-pattern>/CustomCaptchaServlet</url-pattern>
</servlet-mapping>
2> CustomCaptchaServlet.java
package org.example.servlets;
import static nl.captcha.Captcha.NAME;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import nl.captcha.Captcha;
import nl.captcha.servlet.CaptchaServletUtil;
import nl.captcha.servlet.StickyCaptchaServlet;
public class CustomCaptchaServlet extends StickyCaptchaServlet {
private static final long serialVersionUID = 1L;
/**
* #see StickyCaptchaServlet#StickyCaptchaServlet()
*/
public CustomCaptchaServlet() {
super();
// TODO Auto-generated constructor stub
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String _width = getServletConfig().getInitParameter("width");
String _height = getServletConfig().getInitParameter("height");
HttpSession session = request.getSession();
Captcha captcha;
if (session.getAttribute(NAME) == null) {
captcha = new Captcha.Builder(Integer.parseInt(_width), Integer.parseInt(_height))
.addText()
.gimp()
.addBorder()
.addNoise()
.addBackground()
.build();
session.setAttribute(NAME, captcha);
CaptchaServletUtil.writeImage(response, captcha.getImage());
return;
}
captcha = (Captcha) session.getAttribute(NAME);
CaptchaServletUtil.writeImage(response, captcha.getImage());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
Just do this way to by pass what emka86 had said.
<img src="/services/captcha.png" style="display:none"> (Duplicate part to fix the issue)
<img src="/services/captcha.png"> (The actual one)
Hope this helps for any future developer out there.
Check that the web.xml has captcha.png while the HTML is referring to captcha.jpg.
Does that solve the issue?
The problem is that StickyCaptchaServlet is creating new captcha image for session. When you make initial request to a page you have no session id so StickyCaptchaServlet cannot connect you to any image created for a particular session. After first request main servlet create session for you and send you back some kind of sessionId. With next request (also reload) you send to server request with recevied previously sessionId so now your StickyCaptchaServlet is possible to collect captcha image for your session because it knows that you are in any session.
Do you understand this explanation? Will it be helpfull for you?
Added after your question to resolve this problem.
You can add to your web app class which will implements HttpSessionListener. Then, in method sessionCreated you can add request to StickyCaptchaServlet with just created sessionId. According to StickyCaptchaServlet doc You just have to invoke doGet method of it with passed sessionId key. After that - when browser on your page will request for url /services/captcha.png it should get as response image created and prepared just before it by your HttpSessionListener implementation.
Other way is to use cliend side scripting and after page is loaded, with no image at all, just reload it - as this internal reload, for example JavaScript, the browser will know sessionId and will pass it through the request for captcha image. By reload I mean only reload image, not the whole page.
Will any of those suggestions resolve your problem? Give me a feedback about it.
I would like to have my JAX-RX Application start at the root context so my URLs will be
http://example.com/restfullPath
and not
http://example.com/rest/restfullPath
I switched my Application's annotation from this
#ApplicationPath("/rest/*")
to this
#ApplicationPath("/*")
But then it seems that it takes over serving files such as /index.html
Is there a way to run a JAX-RS on the root application context but still have static pages served?
Seems this was asked before on the JBOSS forum, but the solution is not really practical
It's probably not so much a bug as a limitation of the Servlet spec. The details of how a JAX-RS #ApplicationPath is handled is implementation specific, and I can't speak for all implementations, but I'd guess the typical approach is to simply use it as a servlet URL pattern. Taking a look at Jersey's ServletContainerInitializer implementation as one example, you'll find that the addServletWithApplication() method is responsible for creating the servlet and mapping to handle requests, and you can see that it does, indeed, use the path from the #ApplicationPath as the Jersey ServletContainer's mapped path.
Unfortunately, since time immemorial, the Servlet spec has allowed only a small handful of ways of mapping servlets to URL paths. The current options with Servlet 3.0, given in Section 12.2 of the spec--sadly only available as a PDF, so not linkable by section--are:
/.../* where the initial /... is zero or more path elements
*.<ext> where <ext> is some extension to match
the empty string, which maps only to the empty path/context root
/, the single slash, which indicates the "default" servlet in the context, which handles anything that doesn't match anything else
any other string, which is treated as a literal value to match
The same section of the spec also has specific rules for the order in which the matching rules should apply, but the short version is this: to make your resource class answer requests at the context root, you have to use either / or /* as the path. If you use /, then you're replacing the container's default servlet, which would normally be responsible for handling static resources. If you use /*, then you're making it too greedy and saying it should match everything all the time, and the default servlet will never be invoked.
So if we accept that we're inside the box determined by the limitations of servlet URL patterns, our options are fairly limited. Here are the ones I can think of:
1) Use #ApplicationPath("/"), and explicitly map your static resources by name or by extension to the container's default servlet (named "default" in Tomcat and Jetty, not sure about others). In a web.xml, it would look like
<!-- All html files at any path -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<!-- Specifically index.html at the root -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
or with a ServletContextInitializer, like
public class MyInitializer implements ServletContainerInitializer {
public void onStartup(Set<Class<?>> c, ServletContext ctx) {
ctx.getServletRegistration("default").addMapping("*.html");
ctx.getServletRegistration("default").addMapping("/index.html");
}
}
Because of the way the matching rules are written, an extension pattern wins over the default servlet, so you'd only need to add a mapping per static file extension as long as there's no overlap between those and any "extensions" that might occur in your API. This is pretty close to the undesirable option mentioned in the forum post you linked, and I just mention it for completeness and to add the ServletContextInitializer part.
2) Leave your API mapped to /rest/*, and use a Filter to identify requests for the API and forward them to that path. This way, you break out of the servlet URL pattern box and can match URLs any way you want. For example, assuming that all your REST calls are to paths that either begin with "/foo" or are exactly "/bar" and all other requests should go to static resources, then something like:
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.regex.Pattern;
#WebFilter(urlPatterns = "/*")
public class PathingFilter implements Filter {
Pattern[] restPatterns = new Pattern[] {
Pattern.compile("/foo.*"),
Pattern.compile("/bar"),
};
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
String path = ((HttpServletRequest) request).getServletPath();
for (Pattern pattern : restPatterns) {
if (pattern.matcher(path).matches()) {
String newPath = "/rest/" + path;
request.getRequestDispatcher(newPath)
.forward(request, response);
return;
}
}
}
chain.doFilter(request, response);
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {}
#Override
public void destroy() {}
}
With the above, you essentially translate requests as follows:
http://example.org/foo -> http://example.org/rest/foo
http://example.org/foox -> http://example.org/rest/foox
http://example.org/foo/anything -> http://example.org/rest/foo/anything
http://example.org/bar -> http://example.org/rest/bar
http://example.org/bart -> http://example.org/bart
http://example.org/index.html -> http://example.org/index.html
3) Realize that the previous option is basically URL rewriting and use an existing implementation, such as Apache's mod_rewrite, the Tuckey rewrite filter, or ocpsoft Rewrite.
I have found another solution that involves internal Jersey classes, I assume it's probably just not yet part of the JAX-RS spec. (based on: http://www.lucubratory.eu/simple-jerseyrest-and-jsp-based-web-application/)
web.xml
<web-app version="3.0" 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_3_0.xsd">
<display-name>jersey-rest-jsp-frame-1</display-name>
<filter>
<filter-name>jersey</filter-name>
<filter-class>
com.sun.jersey.spi.container.servlet.ServletContainer
</filter-class>
<init-param>
<param-name>
com.sun.jersey.config.property.JSPTemplatesBasePath
</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>
com.sun.jersey.config.property.WebPageContentRegex
</param-name>
<param-value>
(/(image|js|css)/?.*)|(/.*\.jsp)|(/WEB-INF/.*\.jsp)|
(/WEB-INF/.*\.jspf)|(/.*\.html)|(/favicon\.ico)|
(/robots\.txt)
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
WEB-INF/jsp/index.jsp
<%# page contentType="text/html; charset=UTF-8" language="java" %>
<html>
<body>
<h2>Hello ${it.foo}!</h2>
</body>
</html>
IndexModel.java
package example;
import com.sun.jersey.api.view.Viewable;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.net.URI;
import java.util.HashMap;
#Path("/")
#Produces(MediaType.TEXT_HTML)
public class IndexModel {
#GET
public Response root() {
return Response.seeOther(URI.create("/index")).build();
}
#GET
#Path("index")
public Viewable index(#Context HttpServletRequest request) {
HashMap<String, String> model = new HashMap<String, String>();
model.put("foo","World");
return new Viewable("/index.jsp", model);
}
}
This seems to work, but I wonder if it is / will be part of JAX-RS spec / implementation.
You can try to look for DefaultServlet of your servlet container and add servlet-mapping for it by hands in web.xml to handle page files such as *.html, *.jsp or any other.
E.g. for Tomcat 5.5 it's described here: http://tomcat.apache.org/tomcat-5.5-doc/default-servlet.html.
Quoting #damo for Jersey 2.0 from another post
"Alternatively, you might be able to pull something off with some kind of redirection. For example, with a Pre-matching Filter. I've never done anything like this, but the documentation suggests that "you can even modify request URI"."
Use #ApplicationPath("/") instead (without asterisk). It will help in your case.
Here is a sample REST web service:
1. JaxRsActivator.java
package com.stackoverflow;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/")
public class JaxRsActivator extends Application {
}
2. HelloService.java
package com.stackoverflow;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/hello")
public class HelloService {
#GET
#Produces(MediaType.TEXT_HTML)
public String hello() {
return "hello";
}
}
I used Eclipse to export this Dynamic Web project to a WAR file named as helloservice.war and deployed it to WildFly which was running on my local machine. Its URL: http://localhost:8080/helloservice/hello.
When accessing this link it returned:
hello