Cannot make REST call with url-pattern other than /* - rest

I'm trying to do a simple REST Web Application using Tomcat 7, Apache Wink, and the Jackson JSON Processor, but seem to be hitting a wall. If I look in my web.xml file, I see:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Example Web Application</display-name>
<servlet>
<servlet-name>ExampleServlet</servlet-name>
<servlet-class>org.apache.wink.server.internal.servlet.RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.dummy.example.server.ExampleApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
</web-app>
Now, if I substitute /* for the URL pattern instead, the REST call works, but when I use /services/*, it fails.
In my ExampleApplication I see:
package com.dummy.example.server;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
import org.codehaus.jackson.map.AnnotationIntrospector;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector;
import org.codehaus.jackson.xc.JaxbAnnotationIntrospector;
public class ExampleApplication extends Application {
/**
* Get the list of service classes provided by this JAX-RS application
*/
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> serviceClasses = new HashSet<Class<?>>();
serviceClasses.add(com.dummy.example.server.services.Employee.class);
return serviceClasses;
}
#SuppressWarnings("deprecation")
#Override
public Set<Object> getSingletons() {
Set<Object> s = new HashSet<Object>();
// Register the Jackson provider for JSON
// Make (de)serializer use a subset of JAXB and (afterwards) Jackson annotations
// See http://wiki.fasterxml.com/JacksonJAXBAnnotations for more information
ObjectMapper mapper = new ObjectMapper();
AnnotationIntrospector primary = new JaxbAnnotationIntrospector();
AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
AnnotationIntrospector pair = new AnnotationIntrospector.Pair(primary, secondary);
mapper.getDeserializationConfig().setAnnotationIntrospector(pair);
mapper.getSerializationConfig().setAnnotationIntrospector(pair);
// Set up the provider
JacksonJaxbJsonProvider jaxbProvider = new JacksonJaxbJsonProvider();
jaxbProvider.setMapper(mapper);
s.add(jaxbProvider);
return s;
}
}
And in my Employee class, I have:
package com.dummy.example.server.services;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.json.simple.JSONObject;
#Path("/services/employee")
#Produces(MediaType.APPLICATION_JSON)
#SuppressWarnings("unchecked")
public class Employee {
#GET
public JSONObject get() {
JSONObject json = new JSONObject();
json.put("Name", "Example");
return json;
}
}
Any ideas? I've been banging my head against this for some time now

The url-pattern parameter for your servlet (in the web.xml) is independent from the path you specify in your Employee class.
<servlet-mapping>
<servlet-name>ExampleServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
means your servlet listens on the /services/ sub-path.
#Path("/services/employee")
means that your REST application listens on the /services/employee "sub-sub-path".
So your webservice is exposed at localhost:8080/example/services/services/employee (the concatenation of the url-pattern and the #Path annotation).
If you want to expose it at localhost:8080/example/services/employee with the mentioned url-pattern, you need to change the Employee class needs to have:
#Path("employee")

Where would you expect /services/* to go? The web-app states what URL patterns the web application is willing to service. This makes the application server (e.g., JBoss, GlassFish) route /services/foo/bar/whatever to your web application. The Employee class will be invoked in response to a request to /services/employee so you can make that request. Nothing else is registered so /services/* should result in either a 404 or 400 response. Since /services/* is registered to your web application, I would expect a 400.

Related

How to define several ports under single endpoint in CXF?

we're migrating our SOAP application from AXIS2 to CXF and we have following service definition in the wsdl:
<wsdl:service name="MyService">
<wsdl:documentation>My Service
</wsdl:documentation>
<wsdl:port name="MyServiceHttpSoap11Endpoint" binding="ns:MyServiceSoap11Binding">
<soap:address location="http://localhost:8080/axis2/services/MyService" />
</wsdl:port>
<wsdl:port name="MyServiceHttpSoap12Endpoint" binding="ns:MyServiceSoap12Binding">
<soap12:address location="http://localhost:8080/axis2/services/MyService" />
</wsdl:port>
<wsdl:port name="MyServiceHttpEndpoint" binding="ns:MyServiceHttpBinding">
<wsdl:documentation>documentation ***</wsdl:documentation>
<http:address location="http://localhost:8080/axis2/services/MyService" />
</wsdl:port>
</wsdl:service>
In old AXIS2 implementation I was able to access wsdl at http://hostname:port/MyService/services/MyService?wsdl
which had 3 different endpoints for each SOAP version:
/MyService/services/MyService.MyServiceHttpSoap11Endpoint/
/MyService/services/MyService.MyServiceHttpSoap12Endpoint/
/MyService/services/MyService.MyServiceHttpEndpoint/
But how could I achieve same locations with CXF (without Spring)?
I want to have single wsdl url and 3 different locations for each SOAP version.
I know that SOAP 1.2 is backward compatible in CXF, so it's enough to define just 1.2 endpoint to cover SOAP 1.1 and 1.2. But how to use different names for them? And how could I define 3rd port (MyService.MyServiceHttpEndpoint)?
For non-Spring CXF implementation I extended CXFNonSpringServlet class to publish my service:
public class SimpleCXFNonSpringServlet extends CXFNonSpringServlet {
private static final long serialVersionUID = 1L;
#Override
public void loadBus(ServletConfig servletConfig) {
super.loadBus(servletConfig);
Bus bus = getBus();
BusFactory.setDefaultBus(bus);
Endpoint endpoint = Endpoint.create(new EndpointFactory().createMyServiceEndpoint());
endpoint.publish("/MyService");
}
}
Endpoint factory class:
public class EndpointFactory {
public MyServiceHttpSoap12Endpoint createMyServiceEndpoint() {
return new MyServiceHttpSoap12Endpoint(new MyServiceImpl());
}
}
implementor class:
#WebService(
serviceName = "MyService",
portName = "MyServiceHttpSoap12Endpoint",
targetNamespace = "http://company.com",
wsdlLocation = "file:/C:/projects/MyService_CXF/MyService/WebContent/WEB-INF/services/MyService/META-INF/MyService.wsdl",
endpointInterface = "com.company.MyServicePortType")
public class MyServiceHttpSoap12Endpoint implements MyServicePortType {
private static final Logger LOG = Logger.getLogger(MyServiceHttpSoap12Endpoint.class.getName());
private MyServiceAPI myServiceAPI;
public MyServiceHttpSoap12Endpoint(MyServiceAPI myServiceAPI) {
this.myServiceAPI = myServiceAPI;
}
#Override
public ResultObject getObject(Parms pams) throws MyService_Exception {
LOG.info("Executing operation getObject");
// ... implementation ...
}
}
Web.xml:
<servlet>
<servlet-name>CXFServlet</servlet-name>
<display-name>CXF Servlet</display-name>
<servlet-class>
com.company.SimpleCXFNonSpringServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>

jee 6 jaxrs get file not found

I have a utility project having the source and the application
package com.x.framework.api;
import java.security.Principal;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import com.csx.enterprise.webframework.security.LDAPUser;
import com.csx.enterprise.webframework.util.FrameworkThreadProperties;
import com.csx.enterprise.webframework.util.Log;
import com.csx.enterprise.webframework.util.WebFrameworkConstants;
#Stateless
#Path("/security")
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public class SecurityResource {
#Resource
SessionContext ctx;
#GET
#Path("me")
#Produces(MediaType.APPLICATION_JSON)
public Response getMe() {
...
}
package com.x.framework.api;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/api")
public class JaxrsApplication extends Application{
}
I have a web project with web.xml
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.x.framework.api.JaxrsApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>CSXSecurityFilter</filter-name>
<url-pattern>/api/*</url-pattern>
</filter-mapping>
But when I hit the URL https://localhost:9443/webframework/api/security/me, I keeps getting Error 404: java.io.FileNotFoundException: SRVE0190E: File not found: /api/security/me. Any suggestions?
The coding is fine. I had to go to the installedApp directory and extracted the ear file and found the files were not updated accordingly by the Eclipse. So it's not a coding issue, but more of a publishing issue.

Spring Resful WS issue

I'm following http://www.java2blog.com/2015/09/spring-restful-web-services-json-example.html and as it's suggested in the article when I deploy my application to tomcat I get the warning:
WARNING: [SetContextPropertiesRule]{Context} Setting property 'source' to 'org.eclipse.jst.j2ee.server:restordering' did not find a matching property.
(restordering is my application context)
And when I try to access my application I get this warning:
WARNING: No mapping found for HTTP request with URI [/restordering] in DispatcherServlet with name 'restordering'
and I see a 404 error page!
I've tested this on tomcat 7 and 8. I've created the war and deployed outside of eclipse and followed all suggested solution including change in server definition (publish module context to separate XML files) and removing and adding and doing all the tricks it's described in the above article and on stackoverflow but nothing has worked so far.
Before I get "this is a warning and ..." yes it is a warning but also I get 404 error and can't access my services.
And yes I have the correct package name in my restordering-servlet.xml ( context:component-scan base-package="com.obp.restordering.controller" ).
As requested here is my web.xml:
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>restordering</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restordering</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
and restordering-servlet.xml is:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.obp.restordering.controller" />
</beans>
and my controller file is this:
package com.obp.restordering.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.obp.restordering.bean.Country;
#RestController
public class CountryController {
#RequestMapping(value = "/countries", method = RequestMethod.GET, headers = "Accept=application/json")
public List<Country> getCountries() {
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries = createCountryList();
return listOfCountries;
}
#RequestMapping(value = "/country/{id}", method = RequestMethod.GET, headers = "Accept=application/json")
public Country getCountryById(#PathVariable int id) {
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries = createCountryList();
for (Country country : listOfCountries) {
if (country.getId() == id)
return country;
}
return null;
}
// Utiliy method to create country list.
public List<Country> createCountryList() {
Country indiaCountry = new Country(1, "India");
Country chinaCountry = new Country(4, "China");
Country nepalCountry = new Country(3, "Nepal");
Country bhutanCountry = new Country(2, "Bhutan");
List<Country> listOfCountries = new ArrayList<Country>();
listOfCountries.add(indiaCountry);
listOfCountries.add(chinaCountry);
listOfCountries.add(nepalCountry);
listOfCountries.add(bhutanCountry);
return listOfCountries;
}
}
Any idea?
This is embarrassing but I need to come clean and admit and provide an answer so if others have the same issue they don't circle around days as I did.
Arpit the author of the mentioned tutorial responded to my request for help and after checking my code confirmed all works as expected!
The issue was in how I was trying to access my service! If I go to /restordering/countries I get the 404 error. To access the service I need to go to /restordering/restordering/countries! As simple as that.
The warnings I still get and I can't resolve them at this time but at least the service is working and this seems more of a deployment/setting issue than actual spring development issue.
Anyways, I thought this may help some others.
Cheers

Issue when using Jersey 2.x with IBM WAS 8.x to scan and register JAX-RS resources

I am trying to integrate Jersey 2.22.1 with IBM WAS 8.5.4.I have a couple of JAX-RS resources under a certain package (com.innovation.postdata.integration.rest.test.jersey.resources).One of the JAX-RS resource is shown below:
import javax.ws.rs.Consumes;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
#Path("/service")
public class FileSubmissionTestRestService
{
#PUT
#Consumes({ "text/csv" })
#Path("/file")
public Response submitBordereaux (#QueryParam("forceResponse") String forceResponse)
{
if (forceResponse != null && !"".equals (forceResponse))
{
switch (forceResponse)
{
case "404":
return Response.status (Response.Status.NOT_FOUND).entity ("Resource Not Found!").build ();
case "401":
return Response.status (Response.Status.UNAUTHORIZED).entity ("Unauthorized user!").build ();
case "403":
return Response.status (Response.Status.FORBIDDEN).entity ("User not allowed!").build ();
case "405":
return Response.status (Response.Status.METHOD_NOT_ALLOWED).entity ("Unsupported HTTP method!").build ();
case "415":
return Response.status (Response.Status.UNSUPPORTED_MEDIA_TYPE)
.entity ("Media type not supported.It should be TEXT/CSV or APPLICATION/JSON!").build ();
case "500":
return Response.status (Response.Status.INTERNAL_SERVER_ERROR).entity ("Error occured on server!").build ();
default:
return Response.status (Response.Status.NO_CONTENT).build ();
}
}
return Response.status (Response.Status.INTERNAL_SERVER_ERROR).entity ("Error occured on server!").build ();
}
}
and I added a entry in web.xml as shown below
<servlet>
<servlet-name>JAX-RS REST Servlet</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.innovation.postdata.integration.rest.test.jersey.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS REST Servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
I also added a custom run time property(com.ibm.websphere.jaxrs.server.DisableIBMJAXRSEngine) and set it to true in WAS to disable default WAS JAX-RS implementation.The JAX-RS resources (under com.innovation.postdata.integration.rest.test.jersey.resources) are packaged in a separate jar that is added to the main EAR WEB-INF/lib when packaging the EAR. When I start WAS I get to see only this in the start up logs:
[1/5/16 0:27:24:106 GMT-05:00] 00000070 ServletWrappe I
com.ibm.ws.webcontainer.servlet.ServletWrapper init SRVE0242I:
[InnovationInsurer] [/Jasper] [JAX-RS REST Servlet]: Initialization
successful.
No where it says that it tried to scan the resource packages or anything like this.Just this.The jars I am using are:
hk2-api-2.4.0-b31.jar
hk2-locator-2.4.0-b31.jar
hk2-utils-2.4.0-b31.jar
javax.annotation-api-1.2.jar
javax.inject-2.4.0-b31.jar
javax.ws.rs-api-2.0.1.jar
jersey-client-2.22.1.jar
jersey-common-2.22.1.jar
jersey-container-servlet-core-2.22.1.jar
jersey-guava-2.22.1.jar
jersey-media-jaxb-2.22.1.jar
jersey-server-2.22.1.jar
osgi-resource-locator-1.0.1.jar
javassist-3.12.0.GA.jar
aopalliance-1.0.jar
I am using Postman Rest Client to access the JAX-RS at http://10.2.64.3:9080/Jasper/rest/service/file?forceResponse=403 but I am always getting 200 OK which is wrong.Can anybody please help me out as to what could be the reason for this? Why is not even trying to scan the package and only saying servlet successfully initialized.
As far as I know, there is a bug in Websphere that prevent package scanning to work correctly (it works only if the classes are under WEB-INF/classes, not from WEB-INF/lib).
Some informations here: https://developer.ibm.com/answers/questions/169221/packagesresourceconfig.html
I've workarounded that issue using:
public class MyRestApplication extends ResourceConfig {
public MyRestApplication() {
register(DefaultExceptionMapper.class);
register(ConstraintViolationExceptionExceptionMapper.class);
register(JacksonJsonProvider.class);
// does not work in IBM WAS 8.5.5 full profile: see it here
// https://developer.ibm.com/answers/questions/169221/packagesresourceconfig.html
// and
// http://www-01.ibm.com/support/docview.wss?rs=180&uid=swg1PM99378
// packages(getClass().getPackage().getName(), LookupEndpoint.class.getPackage().getName());
// Works under WAS 8.5
registerClasses(LookupEndpoint.class, XEndpoint.class, YEndpoint.class);
}
}
and
<servlet>
<servlet-name>jersey_v2-servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>x.y.z.MyRestApplication</param-value>
</init-param>
<init-param>
<param-name>jersey.config.beanValidation.enableOutputValidationErrorEntity.server</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
That is obviously not optimal (you must maintain yourself the list of endpoints to be used) but at least it works.

The servlets named [Myclass] and [mypropackage.Myclass] are both mapped to the url-pattern [/myclass] which is not permitted [duplicate]

This question already has answers here:
java.lang.IllegalArgumentException: The servlets named [X] and [Y] are both mapped to the url-pattern [/url] which is not permitted
(7 answers)
Closed 6 years ago.
The following error occurs when I start the server
Server Tomcat v7.0 Server at localhost failed to start.
When I look into the console for errors ,I think this is the problem "The servlets named [Myclass] and [mypropackage.Myclass] are both mapped to the url-pattern [/myclass] which is not permitted".
what is the problem here and how to fix it ?
Web.xml code
<?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"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID"
version="3.0">
<display-name>myproject</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>Myclass</servlet-name>
<servlet-class>mypropackage.Myclass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Myclass</servlet-name>
<url-pattern>/myclass</url-pattern>
</servlet-mapping>
</web-app>
Servlet -class code :
package mypropackage;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class Myclass
*/
#WebServlet("/myclass")
public class Myclass extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* #see HttpServlet#HttpServlet()
*/
public Myclass() {
super();
// TODO Auto-generated constructor stub
}
/**
* #see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* #see HttpServlet#service(HttpServletRequest request,
HttpServletResponse response)
*/
protected void service(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
System.out.println("service method");
String uname = "user";
String pass = "abcd";
String un = request.getParameter("username");
String pw = request.getParameter("password");
String msg = " ";
if(un.equals(uname) && pw.equals(pass))
{
msg = "hello" + un + "login successful";
}
else
{
msg = "hello" + pw + "login failed";
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(msg);
}
}
This is logs in console:
Caused by: java.lang.IllegalArgumentException: The servlets named [Myclass] and [mypropackage.Myclass] are both mapped to the url-pattern [/myclass] which is not permitted
at org.apache.catalina.deploy.WebXml.addServletMapping(WebXml.java:293)
at org.apache.catalina.startup.ContextConfig.processAnnotationWebServlet(ContextConfig.java:2428)
at org.apache.catalina.startup.ContextConfig.processAnnotationsStream(ContextConfig.java:2103)
at org.apache.catalina.startup.ContextConfig.processAnnotationsFile(ContextConfig.java:2064)
at org.apache.catalina.startup.ContextConfig.processAnnotationsFile(ContextConfig.java:2057)
at org.apache.catalina.startup.ContextConfig.webConfig(ContextConfig.java:1304)
at org.apache.catalina.startup.ContextConfig.configureStart(ContextConfig.java:889)
at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:386)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5412)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 6 more
You indeed defined your servlet twice:
using #WebServlet("/myclass") annotation into class mypropackage.MyClass
Using web.xml where you defined servlet Myclass.
Both instances of servlet are mapped to the same URL and this is what container tells you. You just should use only one of the ways to define servlet: using annotations or using web.xml. I prefer to use web.xml but probably this is because I used to define servelts there years before the annotations were invented. So, you are welcome to make your choice yourself.
IMHO using web.xml is more flexible. You do not have to decide what is the URL you are mapping your servlet at development time and can deploy the same servlet several times and map it to multiple URLs.