Implementing Rest Easy with Tomcat - rest

I have a Dynamic Web Project with a set of jsp's and a custom controller servlet, that is working great. But, I also need to implement a rest easy exposed service on it, and that's why i changed the web. xml to contain rest easy servlet also. and the application class which invokes the rest easy resource. But, when i am adding changes to web.xml, it is hitting rest easy servlet, but throwing exception..
java.lang.ClassNotFoundException: org.scannotation.AnnotationDB$CrossReferenceException
Web.xml :
<servlet>
<display-name>ControllerServlet</display-name>
<servlet-name>ControllerServlet</servlet-name>
<servlet-class>com.example.ControllerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>CollRestApi</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>com.exampl.RestApiApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ControllerServlet</servlet-name>
<url-pattern>/ControllerServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>CollRestApi</servlet-name>
<url-pattern>/or/*</url-pattern>
</servlet-mapping>
Rest Api Application :
public class RestApiApplication extends Application{
private Set<Object> singletons = new HashSet();
private Set<Class<?>> empty = new HashSet();
public RestApiApplication() {
// ADD YOUR RESTFUL RESOURCES HERE
this.singletons.add(new CollRestApi());
}
public Set<Class<?>> getClasses()
{
return this.empty;
}
public Set<Object> getSingletons()
{
return this.singletons;
}}
And CollRestApi.. is having exposed services..
#Path("api")#Consumes({ "application/xml", "application/json" })#Produces({application/xml", "application/json" })public class CollRestApi {
/**
* #return
*/
#GET
#Path("ab")
public Response do() {
System.out.println("Inside the do Method.");
}}

Obviously, you need to add scannotation.jar to your classpath. RESTEasy 2.2.2.GA depends on scannotation-1.0.3 and javassist-3.12.1.GA.jar which you also need.

I just faced the same problem using maven and netbeans. The answer is to add the jboss maven repository to your pom.xml-file. Just adding <dependency>....</dependency>, e.g. by using netbeans maven browser, doesn't install the dependecies of resteasy.
<repositories>
<repository>
<id>jboss</id>
<url>http://repository.jboss.org/nexus/content/groups/public-jboss/</url>
</repository>
</repositories>

I had the same exception, and fixed it like this:
Is it possible you have the resteasy**.jar libraries in a different location (e.g. the tomcat lib dir) than other resteasy-supporting libs like scannotation-1.0.3.jar (e.g. in your war file WEB-INF/lib) ?
In such a configuration your resteasy classes will start in a different classloader which does not see the scannotation-1.0.3.jar classes.
=> Try putting all resteasy jar files in either one of the locations (preferably your .war file).

Related

Jboss 5, Jersey 2.4, Compressed .war file not working

I am developing some RESTful webservices using the following technologies
* Java 1.7
* Jersey 2.4.1
* spring 3.2.1
* Jboss-5.1.0.GA
So far, I have used eclipse to build the war file, both an exploded version and a compressed version. I have copied the files one at a time to {jboss-home}/server/web/deploy and have started the server using the command line by running run.bat -c web. In both cases the server starts up without error and the log files are identical. (timestamps excluded)
When I deploy the exploded war file and then navigate to the url http://mydomain.com:8080/{app}/rest/application.wadl, jersey is correctly identifying the annotated resources and I can use them as expected.
jersey annotated
#Path("/v1/ping")
#Service("pingV1")
public class PingV1 extends BaseResource {
#Autowired
private PingBusiness pingBusiness;
#GET
#Produces(MediaType.APPLICATION_XML)
public PingVO getPing(
#Context UriInfo uriInfo,
#Context HttpServletRequest httpServletRequest){
...
PingVO pingVO = pingBusiness.doGet();
...
return pingVO;
}
}
application.wadl (dynamically generated)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
<doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 2.4.1 2013-11-08 12:08:47"/>
<grammars>
<include href="application.wadl/xsd0.xsd">
<doc xml:lang="en" title="Generated"/>
</include>
</grammars>
<resources base="http://mydomain.com:8080/{app}/rest/">
<resource path="/v1/ping">...</resource>
<resource path="/">...</resource>
<resource path="application.wadl">...</resource>
</resources>
</application>
However, when I deploy the compressed .war file and navigation to the same url http://mydomain.com:8080/{app}/rest/application.wadl, jersey it not finding the annotated resource and when I hit the expected urls jboss returns a 404 - NOT FOUND.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://wadl.dev.java.net/2009/02">
<doc xmlns:jersey="http://jersey.java.net/" jersey:generatedBy="Jersey: 2.4.1 2013-11-08 12:08:47"/>
<grammars/>
<resources base="http://mydomain.com:8080/{app}/rest/">
<resource path="application.wadl">...</resource>
</resources>
</application>
Lastly, I used winRAR to extract the contents of the compressed war file into a folder, then used Beyond Compare to do a folder comparison of the original exploded war to the contexts that were just extracted and they were IDENTICAL.
This leads me to believe that there is something unique about how jboss deploys exploded wars vs compressed war files, but I don't understand what that may be or why it behaves this way. Can anyone help or point me in a new direction?
While a simple response could be ok, well just deploy the exploded war file, I would like to understand why this happens and continue to use my existing build.xml which produces the compressed .war file.
You can try this:
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(HelloWorldResource.class);
return s;
}
}
or other examples from the Jersey documentation if you want to use reflection to get the resources.
You may have a condition where the unpacking of the war is interfering with the jersey autoscan process and this should fix it.
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.xyz.app.rest.MyApplication</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.xyz.app.rest</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 REST Service</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
package com.xyz.app.rest;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class MyApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(MyDataResource.class);
return s;
}
}

serving HTML/JSP in a restful webapp using jersey & java

I Can't seem to figure it out. tried to use annotations and web.xml to configure paths to webcontent but keep getting unknown resources.
Jersey main:
#ApplicationPath("/")
public class App extends PackagesResourceConfig {
public App() {
super("webapp.resources");
}
}
Jersey default path "/": (hello world works! index.html\jsp does not)
#Path("/")
#Produces(MediaType.TEXT_HTML)
public class RootResource
{
#GET
public String index(#Context HttpServletRequest request) {
return "hello world";
}
}
What I've tried:
multiple web.xml config
serving viewables (error cannot resolve template index.jsp)
what do you think can be a solution to serve pages like html or jsp?
is there a way to do it with jersey (no spring!) and viewable\templates?
to answer my question. futuretelematics's solution should work for most people. it is a known and valid solution. so WHY didn't work when i did it:
question 1:
after much fiddling around i discovered that once i changed the application root path from "/" to "/api" (or /???) suddenly everything started to play along. must be a jersey thing. i read somewhere that in order to make the "/" work you should map with filter in the web.xml. I would love to hear if anyone has done that successfully.
so right now it serves my initial page with JSP. that page i can manipulate with jsons in a rest fashion.
question 2:
making #viewable work was just a matter of creating the right folder structure path in WebContent (com/webapp/model/index(<-- jsp)). that's how the viewable page redirect works.
This should be easy; try the following:
The /WEB-INF/web.xml file:
<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_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<display-name>Your REST end Point</display-name>
<!-- /////////////////////// JERSEY (NO SPRING) ///////////////////////// -->
<servlet>
<servlet-name>MyRESTEndPoint</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<!- Package where jersey will scan for resources ->
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.mycompany</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MyRESTEndPoint</servlet-name>
<url-pattern>/MyRESTEndPoint/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
AT package com.mycompany (look at at the web.xml) place the Application class:
package com.mycompany;
public class MyApp
extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<Class<?>>();
s.add(MyResource.class);
// ... add other resources
return s;
}
}
Create the resource like:
#Path("myResourcePath")
public class R01ERESTResourceForStructure {
#GET #Path("{myResourceId}")
#Produces(MediaType.APPLICATION_XML)
public Response load(#PathParam("myResourceId") final String id) {
....
}
}
Your urls should be: like /MyRESTEndPoint/myResourcePath/myResourceId
If you're using SPRING or GUICE the web.xml should be a bit different
Jersey provides support for JSP templates in jersey-mvc-jsp extension module
check out the official doc

Jersey REST Web Service, Tomcat, Eclipse and 404's

I've read through a number of posts, but just can't seem to solve my problem. You'll also see tons of posts very similar to this one, even the same tutorial. Even following them, I can't seem to get to the answer.
Essentially, I'm trying to follow the simple tutorial at: http://www.vogella.com/articles/REST/
I've made a few changes to make it compatible with Jersey 2.x
I'm using:
Eclipse
Tomcat 6 (Deployed/Run as within Eclipse)
jaxrs-ri-2.0
I've enabled the JAX-RS Facet in Eclipse
Everything builds fine
Tomcat starts fine within Eclipse
I can get to a static page content via:
http://localhost:8080/RestTEST2/index.html
However, when I try to access my service via:
http://localhost:8080/RestTEST2/jaxrs/hello
I receive a 404 with "message not found" and "The requested resource (Not Found) is not available."
Here is my web.xml which is located at /WebContent/WEB-INF/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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>TestREST2</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>TestREST</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
</web-app>
Here is my Java class:
package TestREST;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
// Plain old Java Object it does not extend as class or implements
// an interface
// The class registers its methods for the HTTP GET request using the #GET annotation.
// Using the #Produces annotation, it defines that it can deliver several MIME types,
// text, XML and HTML.
// The browser requests per default the HTML MIME type.
//Sets the path to base URL + /hello
#Path("/hello")
public class Hello {
// This method is called if TEXT_PLAIN is request
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return "Hello Jersey";
}
// This method is called if XML is request
#GET
#Produces(MediaType.TEXT_XML)
public String sayXMLHello() {
return "<?xml version=\"1.0\"?>" + "<hello> Hello Jersey" + "</hello>";
}
// This method is called if HTML is request
#GET
#Produces(MediaType.TEXT_HTML)
public String sayHtmlHello() {
return "<html> " + "<title>" + "Hello Jersey" + "</title>"
+ "<body><h1>" + "Hello Jersey" + "</body></h1>" + "</html> ";
}
}
I also have a JAX-RS User Library configured and referenced that includes all the JAX-RS jars.
Thoughts on what would cause the web service to not be found?
Jersey 2.0 does not recognize init-param with name com.sun.jersey.config.property.packages (web.xml). Try to change it to jersey.config.server.provider.packages as described in ServerProperties.PROVIDER_PACKAGES.
UPDATE (2020): try this link for current apidocs ServerProperties.PROVIDER_PACKAGES:
Thanks a lot.. i've been fighting for it as well.
This combination worked for me:
Tomcat 7.0.55
Eclipse Luna
Java 1.6
Jersey 1.7
web.xml:
<servlet>
<servlet-name>Jersey REST Service</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.trgr.cobalt.cmdb.jersey.resource;com.trgr.cobalt.cmdb.jersey.beans;com.trgr.cobalt.cmdb.elasticity</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>
I would like to add one answer in this post.I was struggling with same problem for two days and couldn't find the solution.
I tried all the possible solutions provided here but later on I realized that server was giving error of
org.glassfish.jersey.servlet.ServletContainer ClassNotFoundException
This link answers gives the solution if somebody is stuck like me..
org.glassfish.jersey.servlet.ServletContainer ClassNotFoundException
Actually first answer given in this post suggest the solution which is for jersey 2.x bundle and if you are using jersey 1.x then it will keep on giving error.
Kindly refer to link given in answer for further reference
Simply by modifying the configuration of Apache Tomcat v7.0 while creating Dynamic Web Project, to include REST, I solved my problem. It is not enabled by default.
Recently I found myself stuck in this problem. I have got it resolved by following these two points as the solution:
By making the src/main/java as the source directory, and keeping the Project Structure as shown below:
Changing com.sun.jersey.config.property.packages to jersey.config.server.provider.packages in the web.xml

Injection of an EJB into a web java class under JBoss 7.1.1

I am trying to build a website using JBoss 7.1.1 and RESTeasy. I have managed to constructed and deploy and EAR with a both a WAR and an EJB-JAR contained within:
voyager-app.ear
META-INF/MANIFEST.MF
META-INF/application.xml
META-INF/jboss-app.xml
lib/voyager-lib.jar
voyager-adm.war
voyager-ejb.jar
voyager-web.war
So far things are very simple. voyager-adm.war & voyager-lib.jar are empty (just the manifest file) but I know that I'm going to have code for them shortly. There is just one Stateful EJB - HarbourMasterBean (with just a local interface) and a few Database Entity Beans in the EJB jar file:
voyager-ejb.jar
META-INF/MANIFEST.MF
META-INF/persistence.xml
com/nutrastat/voyager/db/HarbourMasterBean.class
com/nutrastat/voyager/db/HarbourMasterLocal.class
com/nutrastat/voyager/db/PortEntity.class
com/nutrastat/voyager/db/ShipEntity.class
As far as I can tell the EJBs deploy correctly because the database units are created and the log shows that the publication of some HarbourMaster references:
java:global/voyager-app/voyager-ejb/harbour-master!com.nutrastat.voyager.db.HarbourMasterLocal
java:app/voyager-ejb/harbour-master!com.nutrastat.voyager.db.HarbourMasterLocal
java:module/harbour-master!com.nutrastat.voyager.db.HarbourMasterLocal
java:global/voyager-app/voyager-ejb/harbour-master
java:app/voyager-ejb/harbour-master
java:module/harbour-master
The problem lies in getting the HarbourMaster EJB injected into my web bean. The reference to it is alway NULL no matter what I try.
voyager-web.war
META-INF/MANIFEST.MF
WEB-INF/web.xml
WEB-INF/classes/com/nutrastat/voyager/web/
WEB-INF/classes/com/nutrastat/voyager/web/Ships.class
WEB-INF/classes/com/nutrastat/voyager/web/VoyagerApplication.class
Ships.java:
#Path("fleet")
public class Ships {
protected transient final Logger log;
#EJB
private HarbourMasterLocal harbourMaster;
public Ships() {
log = LoggerFactory.getLogger(getClass());
}
#GET
#Path("ships")
#Produces({"text/plain"})
public String listShips() {
if (log.isDebugEnabled())
log.debug("Harbour master value: " + harbourMaster);
return "Harbour Master: " + harbourMaster;
}
}
<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" >
<display-name>Voyager Web Application</display-name>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</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>
com.nutrastat.voyager.web.VoyagerApplication
</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
I have been searching the web for an answer and read a number of places, both on StackOverflow and elsewhere that suggests is can be done, and that the problems lies with configuration. But they post only snippets and I'm never sure if I'm doing things correctly.
Many thanks for any help you can provide.
Dobbo
What happens if you do:
#Path("fleet")
#Singleton
public class Ships {

what's the "correct" practive for designing the interface for this REST web service?

I'm building a REST web service to manage customers and customer orders.
I'm using Eclipse 3.4 with JAX-RS (Apache Wink 1.0) on WebSphere 7.
I have a web project defined in web.xml like so ...
<servlet>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>org.apache....RestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.mydomain.ws.CustomerWS</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
/***/
</servlet>
... which gives me a URL like http://.../ws/customers that returns all customers.
Now what I need to do is have something like http://.../ws/orders that returns all orders.
My questions are,
I want to add a second web service -- what do I add to the web.xml so that new web service is visible? or am I supposed to create a totally new web project for my second "orders" web service?
or any other ideas? Not sure how to design this "correctly".
Thanks, Rob
I'm not familiar with Wink, but assuming it's JAX-RS-compatible, you should not need any web.xml changes.
If your container is JAX-RS aware,
then annotating your 2nd class with #Path should automatically deploy it
else you can add that new resource class to your REST Application, e.g. based on the example you linked and speculating on your resource class names:
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = new HashSet<Class<?>>();
classes.add(CustomersResource.class);
classes.add(OrdersResource.class);
return classes;
}