am working on implementing Rest web service and need clarification on the deployment descriptor file. Below is the web.xml code and what I have understood is that whenever the url contains /webapi/ the ServletContainer class gets invoked. Please correct me if am wrong till this point. Further can you tell me what's the significance of the attributes param-name and param-value. Is it that the package mentioned in the param-value is passed as argument to the ServletContainer class?
<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container,
see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" 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_2_5.xsd">
<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.xyz.ws.transporter</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
</web-app>
Thanks in advance for your help.
I have understood is that whenever the url contains /webapi/ the ServletContainer class gets invoked.
True.
Further can you tell me what's the significance of the attributes param-name and param-value
init-params are basically just configuration properties that the servlet/filter can use to configure itself.
Here you are configuring a specific property named jersey.config.server.provider.packages, with the value of org.xyz.ws.transporter. Jersey will use the value of the this specific configuration property to set up package scanning. Jersey will scan the package you specify (recursively) for classes annotated with #Provider and #Path. This allows Jersey to register all resources and provider classes.
Related
I need documentation about web.xml and pom.xml files. i would like learn web develop, so i start some tutorials about that. I use IDE eclipse and i choose the option maven project for develop the tutorials. i dont have errors but i cant deploy the projects in web. May be my problems are that i not understand in totality the concept of this files. Some documentation about this i sure that help me. I searched in Satck, in foros but i dont found documentation. I wonder how web developers know the code they need these files
web.xml is web application configuration file defines the servlet container used in the application. You can typically add start-up code, url-pattern as this will be called on application start. Example below extracted from Jersey RestFull service.
<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"
id="WebApp_ID" version="3.0">
<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>com.xxxx.shopper</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/webapi/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.xxxx.shopper.service.Startup</listener-class>
</listener>
</web-app>
pom.xml is maven configuration file defines build process and loads any dependencies.
Good Reads:
1. https://www.mkyong.com/maven/how-to-create-a-web-application-project-with-maven/
2. Difference between web projects with pom.xml and web.xml
3. Why do we use web.xml?
I created a Dynamic Web Project in Java using Eclipse JEE to make a REST web service. I am trying to add a html file simply to add a form that allows me to test my web services in a faster and easier way.
I have read that just placing the html files under the WebContent folder or the WEB-INF folder does the trick. But since I already have a web.xml file it's disrupting the expected behaviour:
This is my web.xml file:
<?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">
<servlet>
<servlet-name>REST web 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>ws,com.fasterxml.jackson.jaxrs.json</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>REST web service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
So where should I place my html files and what should I modify in my web.xml file to get it working (if it needs to be modified)?
In your web.xml you have a mapping for /* which means that the REST web service will receive all the connections, you can either make REST web service return the appropriate resource based on the url or change its mapping (<url-pattern>) to something more specific.
I have a Maven project in Eclipse that is deployed as an EAR containing a JAR module (Java 1.7, EJB 3.1 and JPA 2.0 project) and a WAR module (Servlet 3.0, Java 1.7, JAX-RS 1.1). I am deploying it to a Weblogic 12.1.1.0. The structure is as follows:
backoffice-ear
backoffice-ejb-core-0.0.1-SNAPSHOT.jar
backoffice-ws-0.0.1-SNAPSHOT.war
The WS project has classes that implement REST web services that call the Services and Data Access Objects defined as Stateless EJB in the EJB project. Here's an example:
WAR:
#Path("/Events")
#Stateless
public class EventsWS {
#EJB
private EventsService eventsService;
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/searchEvents")
public Response searchEvents() {
eventsService.searchEvents(null, "S", "TEST", new BigDecimal(1), new BigDecimal(20));
...
}
}
JAR:
#Stateless
public class EventsService {
#EJB
private EventsDao dao;
public DtoSearchEvents searchEvents(...) throws ServiceException {
...
}
}
The injections work fine inside the JAR module. But between the WAR and JAR they don't.
What happens here is that the injected EJB service in EventsWS is always null. But if I load it through JNDI, I am able to use it correctly:
Context context = new InitialContext();
eventsService = (EventsService)context.lookup("java:global/backoffice-ear/backoffice-ejb-core-0.0.1-SNAPSHOT/EventsService");
But I want to be able to inject the EJB without loading it through JNDI. I already tried using #EJB's mappedName attribute with the JDNI path mentioned above but without success. I suppose I am using the correct JNDI path. What am I missing? Let me know if you need more info.
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" version="3.0">
<display-name>backoffice-ws</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>backoffice-ws-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>xxx.yyy.zzz.backoffice.ws</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>backoffice-ws-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Your EventWS is annotated with #Stateless, although it is in the WAR module. What happens is that your #Stateless annotation is ignored (since it's in the WAR), and your EventWS bean is not managed, thus no values are injected.
You need to make the EventWS a managed CDI bean (for example, #RequestScoped). You may want to show the remaining config (web.xml and the JAX-RS annotations that you ommitted) for further help.
Update to answer the question in the comment:
Your are using a non-standard servlet definition. I don't know whether the jersey servlet respects the CDI annotations, therefore you might want to try this in web.xml instead:
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
(or subclass javax.ws.rs.core.Application with the #ApplicationPath annotation. See the Java EE 7 Tutorial for details.)
And then don't for get to annotate your EventWS with #RequestScoped or #SessionScoped or whatever fits your needs.
I am working on project to upgrade my existing web application which is developed in JAX-RS 1.12 and running in tomcat 7. Now I am upgrading it to JAX-RS2.0. During tomcat server startup my resources are not getting loaded ?
Below are the details.
Added below jars for JAX-RS 2.0
jersey-client-2.0-m07-1
jersey-common-2.0-m07-1
jersey-container-servlet-2.0-m07-1
jersey-container-servlet-core-2.0-m07-1
jersey-server-2.0-m07-1
javax.ws.rs-api-2.0-m10
osgi-resource-locator-1.0.1
javax.inject-2.1.28
javax.inject-1
hk2-utils-2.1.28
hk2-locator-2.1.28
hk2-api-2.1.28
guava-13.0
cglib-2.1.28
asm-all-repackaged-2.1.28
In 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_2_5.xsd"
id="WebApp_ID" version="2.5">
<display-name>ConfigLiteJersey2</display-name>
<!-- Jersey Servlet to Support JAXRS Services -->
<servlet>
<servlet-name>ConfigLiteServices</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.core.Application</param-name>
<param-value>com.cisco.config.resource</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ConfigLiteServices</servlet-name>
<url-pattern>/config/*</url-pattern>
</servlet-mapping>
My Resource File
#Path("/configset")
public class ConfigSetResource {
#POST
#Path("/id{configsetid: (/[^/]+?)?}")
#Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public ConfigSetResponse getConfigSet(#PathParam("configsetid") String sConfigSetId) throws Exception {
//Code
}
}
Trying to access my resource API using below URL
ipaddress:8080/ConfigLiteJersey2/config/configset/id
Getting HTTP status 404 Not found.
Looks like I am not giving right servletclass mapping in web.xml. Please share your thoughts on this
If you want Jersey to scan your package for resources, change your param-name to:
<param-name>jersey.config.server.provider.packages</param-name>
I am using Jersey 2.15, and below is working configuration:
<servlet>
<servlet-name>emper</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.le.config.ResourceConfiguration</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.le.exceptions</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>emper</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet>
Great thing that I came to know was, we can register provider class like Global Exception handler. hence com.le.exceptions contain my provider class which implements ExceptionMapper provided by Jersey.
Another thing, We need to create a subclass of org.glassfish.jersey.server.ResourceConfig and register it as our jax-rs application.
If you are using Servlet version 3.0 I would suggest following the example in the jersey manual here: https://jersey.java.net/documentation/latest/deployment.html#deployment.servlet.3.descriptor
Create a class that implements javax.ws.rs.core.Application, say org.foo.rest.ConfigLiteApplication. Then make your web.xml like the following (adapted from the jersey page slightly to match your example):
<web-app>
<servlet>
<servlet-name>org.foo.rest.ConfigLiteApplication</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>org.foo.rest.ConfigLiteApplication</servlet-name>
<url-pattern>/config/*</url-pattern>
</servlet-mapping>
</web-app>
This should work on both JAX-RS 1.1 and JAX-RS 2.0, and should be neutral to the jersey version as you never need to name any jersey classes. The ConfigLiteApplication class should load the resources you want to include, for example adapted from http://tomee.apache.org/examples-trunk/rest-example-with-application/README.html:
#ApplicationPath("/config")
public class ConfigLiteApplication extends Application {
public Set<Class<?>> getClasses() {
return new HashSet<Class<?>>(Arrays.asList(ConfigSetResource.class));
}
}
A modern IDE will likely be able to manage this class for you.
Also, if I were you I would be careful to check this regular expression match if you are hoping to match on /id
#Path("/id{configsetid: (/[^/]+?)?}")
I would consider splitting this up into multiple functions or otherwise working to try and avoid this kind of regex. For example
#POST
#Path("/id")
public ConfigSetResponse getConfigSet() {
return this.getConfigSet(null);
}
#POST
#Path("/id/{configsetid}")
public ConfigSetResponse getConfigSet(#PathParam("configsetid") String sConfigSetId) {
//Code
}
After long Google search, I Configured mine this way and it worked perfectly
build.gradle should be something like this
compile 'log4j:log4j:1.2.7'
compile 'org.slf4j:slf4j-log4j12:1.6.6'
compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.6'
ApplicationConfig.java file should be something like this
#ApplicationPath("/app")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("com.flexisaf.resources");
}
}
Your web.xml file should be something like this
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- Default page to serve -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
<display-name>SAFHRMS</display-name>
<servlet>
<servlet-name>com.flexisaf.safhrms.client.config.ApplicationConfig</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>com.flexisaf.safhrms.client.config.ApplicationConfig</servlet-name>
<url-pattern>/app/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>safhrms.jsp</welcome-file>
</welcome-file-list>
</web-app>
This solves my problems..Thanks
The JAX-RS 1.1 specification says on page 6:
If no Application subclass is present
the added servlet MUST be named:
javax.ws.rs.core.Application
What is the added servlet? Could it be an arbitrary servlet?
If an Application subclass is present
and there is already a servlet defined
that has a servlet initialization
parameter named:
javax.ws.rs.Application
Again, what is "a servlet" here?
If an Application subclass is present
that is not being handled by an
existing servlet then the servlet
added by the ContainerInitializer MUST
be named with the fully qualified name
of the Application subclass.
Does "the servlet added by the ContainerInitializer" mean that the servlets is added automatically? How would a configuration look like?
At the moment I use neither an Application class nor a web.xml and it works (with GlassFish 3.1). Does this deployment mechanism require a full class path scan, which could be slow with big libraries?
How to deploy on a Servlet container?
There is a confusing number of configuration options around in the web. See this example with context params in the web.xml (doesn't work for me!). What is the preferred way to deploy a JAX-RS application?
There are a number of options for deploying into a Java EE 6 container (more specifically a Servlet 3.0 implementation):
The simplest is:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd" version="3.0">
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
Then all the #Path and #Provider classes found in your web application will be available in the "default" JAX-RS application with a servlet URL pattern of "/rest/*".
If you have one or more classes that extends javax.ws.rs.core.Application, you can specify like so:
<?xml version="1.0" encoding="UTF-8"?>
<web-app 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_3_0.xsd" version="3.0">
<servlet>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>com.example.jaxrs.MyApplication</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
</web-app>
You may want to do the above in case you wish to only return specific sets of #Path/#Provider classes on a URL (so you could have a second MyApplication2 with a different URL pattern above).
You can also skip the whole web.xml altogether and just annotate your MyApplication class wih #ApplicationPath which will serve as the URL pattern. I would recommend keeping the web.xml in any case because you will probably have to add other information about the web application there anyway.
If you're wondering where the servlet-class comes from, it is automatically added in by the environment. You can get an idea by looking at the Servlet 3.0 ServletContext.
With WAS 8.5, I change the web.xml to add:
<servlet>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.tada.rest.RestApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
My RestApplication look like :
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;
public class RestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> sets = new HashSet<Class<?>>();
sets.add(RestService.class);
return sets;
}
}
My RestService looks like
#Path("/tada")
public class RestService {
#GET
public String getSomething() {
return "tada";
}
}
And I add in the pom.xml the dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.0</version>
</dependency>
With Servlet3.0, follow this. This works for me.
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.ibm.websphere.jaxrs.server.IBMRestServlet</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>your.restsrv.config.RESTConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<enabled>true</enabled>
<async-supported>false</async-supported>
</servlet>
<servlet>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>javax.ws.rs.core.Application</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
As I said in the comment above, it all depends on the framework you want to use.
http://syrupsucker.blogspot.com/2008/10/deploying-jersey-in-tomcat-60.html for Jersey
http://syrupsucker.blogspot.com/2008/10/deploying-resteasy-in-tomcat-60.html for RESTeasy
As far as I know, JAX-RS does not contain a specification for deployment.