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
Related
I am making a distributed system as a school project and I need to have a REST service. This will be a simple service with a login/register function and some information transfer.
I have made the REST API in Java in NetBeans. It works fine locally, but I am having difficulties to put it on my AWS server. I have no experience with servers, so I don't really know how it works. I thought that it should easy to get the service up and running on a server.
So far I have used this guide for the REST and tried to deploy the war-file with Elastic Beanstalk.
My Java code:
ApplicationConfig.java
package dk.dtu.ds.login;
import java.util.Set;
import javax.ws.rs.core.Application;
#javax.ws.rs.ApplicationPath("CoL")
public class ApplicationConfig extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new java.util.HashSet<>();
addRestResourceClasses(resources);
return resources;
}
/**
* Do not modify addRestResourceClasses() method.
* It is automatically populated with
* all resources defined in the project.
* If required, comment out calling this method in getClasses().
*/
private void addRestResourceClasses(Set<Class<?>> resources) {
resources.add(dk.dtu.ds.login.Login.class);
}
}
Login.java
package dk.dtu.ds.login;
import cleanoutloudserver.ICleanOutLoud;
import java.net.MalformedURLException;
import java.net.URL;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
#Path("login")
public class Login {
// HTTP Get Method
#GET
#Path("dologin")
// Produces JSON as response
#Produces(MediaType.APPLICATION_JSON)
// Query parameters are parameters: http://localhost/colrest/CoL/login/dologin?username=s150157&password=1234
public String doLogin(#QueryParam("username") String uname, #QueryParam("password") String pwd) throws MalformedURLException, Exception {
URL url = new URL("http://ec2-52-43-233-138.us-west-2.compute.amazonaws.com:3769/col?wsdl");
QName qname = new QName("http://cleanoutloudserver/", "CleanOutLoudImplService");
Service service = Service.create(url, qname);
ICleanOutLoud col = service.getPort(ICleanOutLoud.class);
String token = col.login(uname, pwd);
token = Utility.constructJSON(token);
System.out.println("\nChecking credentials = true\n");
return token;
}
}
web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>RESTWebApp</display-name>
<servlet>
<servlet-name>jersey-servlet</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>dk.dtu.ds.login</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
When I then try to open the path for the service, I get a blank page. My Chrome console says "GET (link) 404 (Not Found)"
Since I am not that familiar with HTTP and servers, I don't know what to do.
Isn't there an easy way to deploy a simple REST service with AWS or have I done something wrong?
I have really tried to search google to find help, but there has been no success so far.
It seems like i got too confused by all the guides out there.
I found an easy solution and installed Tomcat on the EC2 instance, so I didn't even need to use Beanstalk.
All I did was following this guide and uploaded the war-file in the Web Application Manager and now it works fine.
Thanks for the comments they helped me on the way to find a solution.
I am trying to invoke this exception mapper to return a 404 not found response but it keeps returning 500 internal error. Jersey version is 2.22.1. Code snippet below. Appreciate all help.
Thanks.
Exception mapper class.
package org.learn.rest.messengerdemo.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException>{
#Override
public Response toResponse(DataNotFoundException ex) {
return Response.status(Response.Status.FORBIDDEN).build();
}
}
Exception Class.
package org.learn.rest.messengerdemo.exception;
public class DataNotFoundException extends RuntimeException{
private static final long serialVersionUID = 2176642539344388961L;
public DataNotFoundException(String message)
{
super(message);
}
}
Service class's method that throws.
public Message getMessage(long messageId) {
Message message = messages.get(messageId);
if(message == null)
{
throw new DataNotFoundException("Message with id " + messageId + " not found");
}
return message;
}
And the resource class.
#GET
#Path("/{messageId}")
public Message getMessage(#PathParam("messageId") long messageId) {
return messageService.getMessage(messageId);
}
Looking at the web.xml from your previous question, you have this
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.learn.rest.messengerdemo.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
What this init-parm jersey.config.server.provider.packages says is that Jersey should scan the named package for #Path annotated resource class and #Provider annotated provider classes and register them.
You only have the resources package org.learn.rest.messengerdemo.resources listed, but you ExceptionMapper is in a different package. The default behavior is to scan recursively, meaning sub-packages also. So if you listed org.learn.rest.messengerdemo instead, you would hit both the resources package and the exceptions package. Or you could list both packages, separated by comma or semi-colon. Either way would work
<param-value>org.learn.rest.messengerdemo</param-value>
<!-- OR -->
<param-value>
org.learn.rest.messengerdemo.resources,
org.learn.rest.messengerdemo.exception
</param-value>
Please note that this is not problem of annotation. i have seen people given comments that due to #Provider annotation its not registered, if you have imported correct provider it will work. Please find my solution below
I have encountered the same issue while develop sample REST API. While creating REST API i have given base package name like org.manish.rest.message, I supposed to create every other packages under the base package like this
model - org.manish.rest.message.model
database - org.manish.rest.message.database
resource - org.manish.rest.message.resource
in web.xml init param was given like this
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.manish.rest.message</param-value>
</init-param>
It means, i have registered my base package in web.xml, what ever package i will create under this; will be consider by JAX-RS based on my call and requirement. But when i created my exception package by mistake i put package name org.manish.rest.exception. Since this was not registered in web.xml so my complete exception class was not considered to handle exception by JAX-RS. As a correction, i have just modified my exception package name from org.manish.rest.exception to org.manish.rest.message.exception
After that i executed once in post man and i got expected result.
Hope this can solve your query.
Thanks Manish
I'd like to propose another option ...
change the mapper package to match the resource package where the exception could normally be caught.
Assuming the resource classes package is:
package org.learn.rest.messengerdemo.resources;
change the mapper class package from:
package org.learn.rest.messengerdemo.exception;
to:
package org.learn.rest.messengerdemo.resources;
That way you won't be fiddling with framework generated files or uncommon syntax.
I still don't grasp why a try/catch isn't used but I'm rebuilding my Java knowledge so I won't inject an opinion or request any. If its current practice then I'll learn that soon enough. And mappers are an interesting opportunity at that.
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/
I am trying to invoke this exception mapper to return a 404 not found response but it keeps returning 500 internal error. Jersey version is 2.22.1. Code snippet below. Appreciate all help.
Thanks.
Exception mapper class.
package org.learn.rest.messengerdemo.exception;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException>{
#Override
public Response toResponse(DataNotFoundException ex) {
return Response.status(Response.Status.FORBIDDEN).build();
}
}
Exception Class.
package org.learn.rest.messengerdemo.exception;
public class DataNotFoundException extends RuntimeException{
private static final long serialVersionUID = 2176642539344388961L;
public DataNotFoundException(String message)
{
super(message);
}
}
Service class's method that throws.
public Message getMessage(long messageId) {
Message message = messages.get(messageId);
if(message == null)
{
throw new DataNotFoundException("Message with id " + messageId + " not found");
}
return message;
}
And the resource class.
#GET
#Path("/{messageId}")
public Message getMessage(#PathParam("messageId") long messageId) {
return messageService.getMessage(messageId);
}
Looking at the web.xml from your previous question, you have this
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.learn.rest.messengerdemo.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
What this init-parm jersey.config.server.provider.packages says is that Jersey should scan the named package for #Path annotated resource class and #Provider annotated provider classes and register them.
You only have the resources package org.learn.rest.messengerdemo.resources listed, but you ExceptionMapper is in a different package. The default behavior is to scan recursively, meaning sub-packages also. So if you listed org.learn.rest.messengerdemo instead, you would hit both the resources package and the exceptions package. Or you could list both packages, separated by comma or semi-colon. Either way would work
<param-value>org.learn.rest.messengerdemo</param-value>
<!-- OR -->
<param-value>
org.learn.rest.messengerdemo.resources,
org.learn.rest.messengerdemo.exception
</param-value>
Please note that this is not problem of annotation. i have seen people given comments that due to #Provider annotation its not registered, if you have imported correct provider it will work. Please find my solution below
I have encountered the same issue while develop sample REST API. While creating REST API i have given base package name like org.manish.rest.message, I supposed to create every other packages under the base package like this
model - org.manish.rest.message.model
database - org.manish.rest.message.database
resource - org.manish.rest.message.resource
in web.xml init param was given like this
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>org.manish.rest.message</param-value>
</init-param>
It means, i have registered my base package in web.xml, what ever package i will create under this; will be consider by JAX-RS based on my call and requirement. But when i created my exception package by mistake i put package name org.manish.rest.exception. Since this was not registered in web.xml so my complete exception class was not considered to handle exception by JAX-RS. As a correction, i have just modified my exception package name from org.manish.rest.exception to org.manish.rest.message.exception
After that i executed once in post man and i got expected result.
Hope this can solve your query.
Thanks Manish
I'd like to propose another option ...
change the mapper package to match the resource package where the exception could normally be caught.
Assuming the resource classes package is:
package org.learn.rest.messengerdemo.resources;
change the mapper class package from:
package org.learn.rest.messengerdemo.exception;
to:
package org.learn.rest.messengerdemo.resources;
That way you won't be fiddling with framework generated files or uncommon syntax.
I still don't grasp why a try/catch isn't used but I'm rebuilding my Java knowledge so I won't inject an opinion or request any. If its current practice then I'll learn that soon enough. And mappers are an interesting opportunity at that.
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.