RESTEasy (jax-rs), multiple packages declaration in web.xml? - rest

How to declare multiple packages in the web.xml for the RESTEasy jax-rs provider?
If I have:
<web-app id="WebApp_ID" version="2.4"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Restful Web Application</display-name>
<!-- this need same with resteasy servlet url-pattern -->
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</context-param>
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher </servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>part1.MessageApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
It's working.
But If I have :
And then change the declaration of the web.xml (which is based on this way, which may have already worked in Jersey)
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class> org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher </servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>part1.MessageApplication;part2.MessageApplication2</param-value>
</init-param>
</servlet>
Whenever I try to access a #Path-mapped-class in package "part2" it will throw :
java.lang.RuntimeException: java.lang.ClassNotFoundException: part1.MessageApplication;part2.MessageApplication2 from
Note that I'm aware that I've changed the #Path-mapped-class with different url path like #Path("controller2").
How do I configure it properly in the web.xml?

Not sure if I clearly understand your problem. The link you provided in your question is about specifying multiple packages. But looks like you are dealing with two Application subclasses. It's a different matter.
In this situation, you should register two HttpServletDispatcher mapped to different URI patterns, as following:
<!-- Application 1 (part1.MessageApplication) mapped to /rest/app1/* -->
<servlet>
<servlet-name>resteasy-application1</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>part1.MessageApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-application1</servlet-name>
<url-pattern>/rest/app1/*</url-pattern>
</servlet-mapping>
<!-- Application 2 (part2.MessageApplication2) mapped to /rest/app2/* -->
<servlet>
<servlet-name>resteasy-application2</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>part2.MessageApplication2</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-application2</servlet-name>
<url-pattern>/rest/app2/*</url-pattern>
</servlet-mapping>
Each Application subclass is mapped to a path that serves as the base URI for the resource URIs provided by #Path annotation.
You could have multiple Application subclasses when you support multiple versions of the API, for example. For simple applications, it's very likely you don't need that.
You may not need a web.xml
As per your comment, you are using WildFly 8. It's Servlet 3.0 compatible so you don't even need a web.xml deployment descriptor for simple applications. Most of the configurations, such as registering servlets, filters and listeners can be done via annotations.
In case you are not providing a web.xml deployment descriptor for your Maven-based web application project, you need to configure your maven-war-plugin to ignore the missing web.xml file by setting the failOnMissingWebXml configuration property to false in your project pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
Since the version 3.0.0 of the maven-war-plugin, the default value for failOnMissingWebXml has been changed from true to false. You can use the most recent version and ommit that configuration property.
If, for some reason, you want to keep the web.xml, it can be as simple as:
<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_3_0.xsd"
version="3.0">
</web-app>
A few words on the Application class
Regarding JAX-RS, annotate your Application subclass with #ApplicationPath specifying the base URI for your resource classes:
#ApplicationPath("api")
public SampleApplication extends Application {
}
In the example above, the JAX-RS runtime will scan the classpath for JAX-RS components and will register them automatically.
If you want to manually register your resources and providers (preventing the JAX-RS runtime from registering the components automatically), override the getClasses() and/or the getSingletons() methods:
#ApplicationPath("api")
public SampleApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.add(MyResource.class);
resources.add(MyOtherResource.class);
return resources;
}
}
For more details on the Application class, this answer can provide you some insights.
Managing your dependencies
It's worthwhile to mention that RESTEasy 3.x is shipped with WildFly. If you will use only the JAX-RS API the following dependency will give you all you need:
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
If you need to use any type from the RESTEasy API, add the RESTEasy 3.x dependencies with the provided scope. It tells Maven that the container will provide that dependency, hence they won't be shipped with your application. Failing to provide the right scope may cause some weird errors and bad headaches. For more details on scopes, check the dependency scope documentation.

Related

WebLogic changes the url-pattern of RESTful

After deploying my war file, Weblogic changes the url-pattern, which i've defined in web.xml for my Jersey RESTful. As you can see, I want to access my service under /rest/* but weblogic changes it to /resources/*. Where can I configure it for WebLogic?
<servlet>
<servlet-name>jersey-serlvet</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>ch.ni.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
p.s it works with tomcat, as desired
I ran into a similar problem moving an application from Glassfish 3 to Weblogic 12.2.1. I finally caved in and followed the Jersey tutorial here.
I used the web.xml that was generated in the example to fix the code I was working on.
Short answer is I had to change the web.xml servlet definition to look like:
<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>your.package.with.JAXRS.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webservices/*</url-pattern>
</servlet-mapping>
I also took the dependencies from the POM in the example and used them in my POM.
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>2.24</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.24</version>
</dependency>
Hope it helps.

RESTEasy - Resource Class Register Failed when #Path is Marked in the Interface

I am using RESTEasy 2.0.1.GA on Jboss 4.3.0.GA.
The interface that my resource class implemented looks like this:
#Path("/")
public interface CwindRestfulService {
#GET
#Path("accounts/{email}")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Account getAccountInfo(#PathParam("email") String email) throws Exception;
}
When I set resteasy.scan=true in web.xml, it works fine. But it should be false with spring context. So now my web.xml is:
<web-app>
<display-name>Archetype RestEasy Web Application</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/applicationContext.xml</param-value>
</context-param>
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.cwind.rest.CwindRestfulServiceImpl</param-value>
</context-param>
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
And I got this error:
2014-02-20 18:10:23,303 ERROR [org.apache.catalina.core.ContainerBase] Exception sending context initialized event to listener instance of class org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
java.lang.RuntimeException: Class is not a root resource. It, or one of its interfaces must be annotated with #Path: com.cwind.rest.CwindRestfulServiceImpl implements: com.cwind.rest.CwindRestfulService
It suggested that I missed #Path while actually I didn't. But when I put the annotation to the resource class it does work. I googled and found a solution in http://pilhuhn.blogspot.com/2011/06/seemingly-common-resteasy-error-and.html. It needs to add a #ApplicationPath annotation. Now my interface is in a third party lib so I can't modify it. Does anybody have some suggestions? Thanks in advance.
It appears that you have not registered a Resteasy specific SpringContextLoaderListener. This is required for Spring to register scanned resource classes with Resteasy.
Below is an example web.xml configuration (this uses annotation configuration, but will also work with xml configuration):
<!-- Spring Configuration -->
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.myapp.SpringConfig</param-value>
</context-param>
<!-- RESTEasy Configuration -->
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/</param-value>
</context-param>
<!-- RESTEasy <-> Spring Connector (Needed so that RESTEasy has access to Spring managed beans!) -->
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<!-- RESTEasy HTTP Request Processor Servlet -->
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Then you simply annotate your resource classes for Spring either with #Component or #Named as shown below:
#Named
#Path("/")
public class MyResource implements CwindRestfulService
{
//Stuff Goes Here...
}

Jersey 2.1 + JBoss 7.1 NoSuchMethodError: getProperties

I am trying to run Jersey 2.1 REST service on JBoss 7.1 AS. I am getting the NoSuchMethodError: javax.ws.rs.core.Application.getProperties error during deployment:
ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/RESTService]] (MSC service thread 1-9) StandardWrapper.Throwable: java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:271) [jersey-server-2.1.jar:]
at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:283) [jersey-container-servlet-core-2.1.jar:]
In pom.xml I have:
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.1</version>
</dependency>
And in the web.xml:
<servlet>
<servlet-name>RESTService</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.gatekeeper.restservice.RESTApplication</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Previously I tried with Jersey 1.17.1 and it worked (after disabling resteasy scan and jaxrs extension/subsystem in JBoss). So far I've found one similar post (but with Tomcat) where the conslusion was that the wrong javax.ws.rs.core.Application is being bound at runtime, and further that the bound class is an "old" (JAX-RS 1.1) version.
Any help how to resolve this? I'm .net guy and I'm totally blind in java :)
Thanks
Bartek
I know this thread is not that fresh, but still, I only hit this problem yesterday and nothing seems to work.
My scenario is very similar: Jersey 2.23.1 REST App (JAX-RS 2.x) already running on tomcat and need to run on JBoss 7.1.1 (built-in JAX-RS 1.1).
Turn off Restease package scanning in your web.xml:
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.providers</param-name>
<param-value>false</param-value>
</context-param>
<context-param>
<param-name>resteasy.scan.resources</param-name>
<param-value>false</param-value>
</context-param>
Remove all tags with "jaxrs" from standalone.xml. Otherwise you will still face LinkageError because JBoss keeps 1.1 spec on.
Create yourApp.war!WEB-INF\jboss-deployment-structure.xml just like is pointed out here: https://docs.jboss.org/author/display/AS7/Class+Loading+in+AS7#ClassLoadinginAS7-JBossDeploymentStructureFile
This way, not only:
java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
Disapears, but also, JAXB works fine (No ClassNotFoundException for javax.xml.bind.JAXBException once module javax.xml.bind.api is also activated).
Obs1: The original question is mixing jersey 1.x with jersey 2.x. There is no PojoMappingFeature in jersey 2.x and base package is org.glassfish.jersey. Take a look at https://jersey.java.net/documentation/latest/migration.html#mig-1-x-json
Obs2: I have also tried other approaches like extending ResourceConfig and scanning packages from there or registering classes directly. Nothing worked like the proper documentation in item 3. So kept my servlet untouched:
<servlet>
<servlet-name>WebNize REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>br.com.webnize.rest.service</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebNize REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
I hope it helps others!
In short, significant structural changes have been made between 1.17 and 2.2 of the Jersey implementation. You need to:
1) Extend your application class from "org.glassfish.jersey.server.ResourceConfig"
2) Add the packages line within the application class constructor, like so:
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("com.mysite.MyApplication");
}
}
3) Within web.xml, you'll need to update a number of places. See below:
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mysite.MyApplication</param-value>
</init-param>
4) Deploy and have fun.
Additionally, it seems that the practice of using wildcards within the java source is deprecated.
Not this)
#Path("/v1/status/*")
But this)
#Path("/v1/status")
An improvement, IMHO.

java web service (jersey) on tomcat only works when running from eclipse

I developed few web services using Eclipse and Jersey and Tomcat 7 as the server.
When running the project from Eclipse, everything works fine. However, when deploying the project WAR file directly to Tomcat (using it's manager), I'm getting 404 error when calling the service.
My WEB-INF\lib directory contains all jersey libs.
my 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_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>myApp</display-name>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>myApp REST Service</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.myapp.resources</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myApp REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
I believe I'm missing something on the Tomat configuration, but have no idea...
Any idea?
Ahanks,
Assaf
ok...
problem solved by taking the following two actions:
a. configuring the following entries of \tomcat\conf\server.xml, replacing the "localhost" attribute with the actual server name:
<Engine name="Catalina" defaultHost="localhost">
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
b. taking care of windows firewall, to allow inbound http:8080. I'm feeling a bit embarrassed - for some reason I thought setting the Amazon security rules was enough (-:
Thanks for your attention.
Assaf
Try This one ...
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.hrms.admin.jersey.service</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Visit This one : Jersey

Resource not available problem

I get a HTTP Status 404 - Requested resource (/Fun/hello) is not available.
I am running Tomcat 7.0, Jersey 1.8, Java 1.6, Eclipse Helios 2.
I am working from a tutorial by Lars Vogel.
As far as I can tell, the resource is being loaded:
INFO: Root resource classes found:
class bighello.Hello
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>Fun</display-name>
<servlet>
<servlet-name>Jersey REST Service</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>bighello</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Any ideas?
In the web.xml , you only map one URL pattern , which is /rest/* to call the servlet.
But now , your request URL is /Fun/hello , which does not match any URL patterns you defined in the web.xml , so it returns HTTP Status 404
In fact, refer to section 3.4 of your mentioned tutorial , you should test your REST service under: http://localhost:8080/de.vogella.jersey.first/rest/hello.