Configuring provider packages in web.xml with Jersey - java

I am working on a web service and I get very strange error.
This is the line from my web.xml:
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>service</param-value>
</init-param>
As I know, <param-value> has to be referred in to the package my main application is. However, my application is in rest.main package, but the web service works only with the service value as defined above.
What is the problem, can somebody explain me these lines?

Have a look at the documentation regarding the jersey.config.server.provider.packages configuration property:
Defines one or more packages that contain application-specific resources and providers. If the property is set, the specified packages will be scanned for JAX-RS root resources and providers.
Servlet 2.x containers
This setting is frequently used in the web.xml deployment descriptor to instruct Jersey to scan these packages and register any found resources and providers automatically:
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
org.foo.myresources,org.bar.otherresources
</param-value>
</init-param>
With this setting, Jersey will automatically discover the resources and providers in the selected packages. By default, Jersey will recursively scan the sub-packages as well.
Servlet 3.x containers
For Servlet 3.x containers, no web.xml is necessary at all. Instead, an #ApplicationPath annotation can be used to annotate a custom Application or ResourceConfig subclass and define the base application URI for all JAX-RS resources configured in the application.
Use the following to defined the packages that will be scanned:
#ApplicationPath("resources")
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("org.foo.myresources,org.bar.otherresources");
}
}
For more details, check the deployment section of the Jersey documentation.
Important
Always use the qualified name of the package;
Use , or ; as delimiter when declaring multiple packages.

You just need to add the package name to the
Form an Example if I have placed my resource class in com.ft.resources package
then I have to add the package name in
<init-param>
<!-- For Jersey 2.x -->
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>com.ft.resources</param-value>
</init-param>
Hope this might resolve your issue

If the application consists only resources and providers stored in particular packages, Jersey can scan them and register automatically.
<web-app>
<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.foo.rest;org.bar.rest</param-value>
</init-param>
...
</servlet>
...
</web-app>
The param-value refers to the packages which will be scanned automatically.

Related

How to fix 'cannot be cast to javax.servlet.Servlet' error while trying to package REST App with Servlet

I am trying to setup Angular 7 with a maven based back-end java project into a single war file. At the moment I am trying to configure the web.xml file where I am currently having this problem. I am not sure at all if my approach is valid or 'good' therefore I will first describe what I am trying to do (if you think better on this aspect please do correct me).
So I have a couple of JAX-RS classes which I'd like to serve as a REST API. For this purpose I have created corresponding javax.ws.rs.core.Application classes to provide these REST components. Then I am including the Application classes in the web.xml file. Below are the files:
web.xml
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<url-pattern>/rmz/*</url-pattern>
</servlet-mapping>
Another variation of web.xml that I tried
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>backend.backendservice.StammSolvaraJahrRestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>backend.backendservice.StammSolvaraJahrRestApplication</servlet-name>
<url-pattern>/rmz/*</url-pattern>
</servlet-mapping>
Application class
public class StammSolvaraJahrRestApplication extends Application {
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> sets = new HashSet<>();
sets.add(StammSolvaraJahrRest.class);
return sets;
}
}
The error that I get is: java.lang.ClassCastException: backend.backendservice.StammSolvaraJahrRestApplication cannot be cast to javax.servlet.Servlet and if I remove the <servlet-class> then I'll get No servlet class has been specified for servlet. I am following https://docs.oracle.com/cd/E24329_01/web.1211/e24983/configure.htm#RESTF183 and How to deploy a JAX-RS application? among others but it seems not to be working.
There are two ways to define your JAX-RS servlet.
1) With Application Subclass like the one you have, you can skip the web.xml config and just add the application annotation
#ApplicationPath("resources")
public class StammSolvaraJahrRestApplication extends Application
2) With web.xml config
<servlet>
<display-name>JAX-RS Servlet</display-name>
<servlet-name>package.hierarchy.StammSolvaraJahrRestApplication</servlet-name>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>package.hierarchy.StammSolvaraJahrRestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>JaxRSServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
If you skip the servlet mapping from the last one, it will use your your #ApplicationPath specified value, or "/resources" if the previous one is missing.
The problem is just what it says. This line in your web.xml requires a javax.servlet.Servlet:
<servlet-class>backend.backendservice.StammSolvaraJahrRestApplication</servlet-class>
Since an Application is not a javax.servlet.Servlet, you're getting the error at runtime when your XML file is processed.
If you can, I would suggest that you start with a Spring Boot starter application. Spring Boot handles all of this for you. It can even embed a Tomcat server inside a jar file so that you can run your server like a simple Java application. Doing this would save you having to worry about what you're dealing with here.

Jersey 2.22: Where should I define the location of REST resources?

Currently, I know two ways:
Specify it as an <init-param> on you web.xml
Create a class that extends ResourceConfig and add it on your web.xml
I have this class that extends ResourceConfig because I needed to register an Application Binder (AbstractBinder) for dependency injection.
Where should I define the location of my REST resources? What's the best practice here?
In the ResourceConfig, you can call packages("reource.packages"), which will do the same as scanning the package declared inside the <init-param>
public class Config extends ResourceConfig {
public Config() {
packages("...");
register(new AbstractBinder()..);
}
}
To use the Config class, you have a couple options.
Annotate it with #ApplicationPath("/appPath")
With this, no web.xml is required. You need to make sure you have the jersey-container-servlet dependency for this to work. The value in the annotation works the same way as the <servlet-mapping> inside the web.xml.
Declare the Config class inside the web.xml
<servlet>
<servlet-name>MyApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.foo.Config</param-value>
</init-param>
</servlet>
...
<servlet-mapping>
<servlet-name>MyApplication</servlet-name>
<url-pattern>/myPath/*</url-pattern>
</servlet-mapping>
You could also not use the ResourceConfig and register the binder inside a Feature, as discussed here
See Also:
Application Deployment and Runtime Environments: Servlet-based Deployment
How to use Jersey as JAX-RS implementation without web.xml?

how to load a class during start up in spring, I am new to spring

how can application itself be inserted in database during startup only once.
I already tried using #postconstruct to do this.
When using Spring the following are common usage scenario's.
If you are building a web application you add some configuration to web.xml, for example (example for Spring 3):
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/dispatcher-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
This makes sure the Spring application context in the file /WEB-INF/spring/dispatcher-config.xml is loaded when the web application is loaded by the container (e.g. Tomcat). Your application will in this case probably contain of controllers of some sort (classes which handle requests) and these can be set up in spring to be injected with dependencies from the application context.
If you are building a standalone application you need to start it using the main method as usual. To load the Spring application context you need to do something like this:
ApplicationContext context = new ClassPathXmlApplicationContext("path/to/applicationContext.xml");
MyApplication app = (MyApplication )context.getBean("myApp");
app.doSomething();
This loads the application context from the classpath.

Two separate Spring contexts for one webapp

I want to use two different Spring web contexts, each have own contextConfig, spring servlet and filter, that should be mapped to different urls. I have a
Standard Grails project, mapped to '/'
And an existing Spring webapp, that I want to map to /extra/
I know that I can deploy both into one Tomcat, but I'm looking for a way of making one app (one war, etc), because It can simplify our deployment and development process.
This applications don't need to share beans or anything, should be completely separate. Both have DispatcherServlet and DispatcherFilter (and both are using Spring Security, but different configuration)
How I can configure web.xml for such webapp?
I've tried to add new filter:
<filter>
<filter-name>extraSpringSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
</init-param>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>extraSecurityFilterBean</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>extraSpringSecurityFilterChain</filter-name>
<url-pattern>/extra/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
and spring dispatcher servlet:
<servlet>
<servlet-name>extraSpring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>springConfigLocation</param-name>
<param-value>classpath:extra-spring-web.xml</param-value>
</init-param>
</servlet>
Where:
two context xml in classpath (inside exra library jar):
extra-spring-web.xml
extra-spring-security.xml (!!! how I should configure it?)
extra-spring-security.xml
is pretty standard Spring Security config
have configured bean extraSecurityFilterBean
have dependecy to beans from -web context (but it's not required to be)
It's semi-working now:
as I see from logs, extraSpring servlet successfully load beans from extra-spring-web.xml
but after accessing url /extra/ I got NoSuchBeanDefinitionException: No bean named 'extraSecurityFilterBean' is defined.
So, the question, how I can define context for DelegatingFilterProxy? I even tried to add this files into main context (contextConfigLocation param), it's not what i'm looking for, but it didn't work.
I've taken a look into DelegatingFilterProxy sources, but it's not clear for me how it loads the context.
As per my comment on the question, if the security filter chain is defined in extra-spring-security.xml then you need to ensure that that file is loaded by your extra DispatcherServlet in addition to extra-spring-web.xml either by <import>ing the -security file from the -web one or configuring it as:
<servlet>
<servlet-name>extraSpring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:extra-spring-web.xml
classpath:extra-spring-security.xml
</param-value>
</init-param>
</servlet>
You will also need to ensure that the security filter in the Grails application doesn't apply to /extra URIs, exactly how you do this depends on whether you're using annotations, database RequestMap entries etc.
If the modules are completely separate: the easiest way is to package them as two different webapp. Tens of different spring-based apps can run in one appserver -even on a modest developer machine- without issues.
A few questions
What does your Spring Security configuration look like?
I'm confused why the error states "No bean named 'apiservSecurityFilterChain' is defined" but the web.xml you have posted only references extraSpringSecurityFilterChain (the bean names should match or some important configuration is being left out).
Possible Answer
I'm guessing the problem is that the filter-name needs to match Spring Security's bean name (cannot know for sure without seeing the Spring Security configuration you are using). The default value used by the Spring Security namespace is springSecurityFilterChain, so try the following in the web.xml instead (notice extraSpringSecurityFilterChain changed to springSecurityFilterChain):
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>contextAttribute</param-name>
<param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.extraSpring</param-value>
</init-param>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>extraSecurityFilterBean</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/extra/*</url-pattern>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>

Tomcat 6.x web.xml default and custom servlet routing

I have two servlets defined in the web.xml file, namely the default2 and myservlet. The default2 servlet is used to map the static files like the javascript and css. The myservlet is used for getting dynamic content.
<servlet>
<servlet-name>default2</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>myservlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath:my-servlet.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
The servlet mapping is defined as follows
<servlet-mapping>
<servlet-name>myservlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default2</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
When i try to access any files under /resources, i get a 404. Any ideas why this config is not working or change this config to make it work.
Tomcat's default servlet before 6.0.30 actually serves a static resource identified by HttpServletRequest.getPathInfo(), so that /style.css will be returned when /resources/style.css is requested.
Tomcat's behavior has changed from version 6.0.30 onwards. So the original configuration from the question works in newer versions of Tomcat. See "50026: Add support for mapping the default servlet to URLs other than /. (timw)" in the changelog.
Jetty's default servlet uses a full path.
It should work fine. Are those files in real also located in the /resources folder?
Your web.xml looks correct (except I would change your <load-on-startup> constants).
Make sure that your /resources exists and is a publicly visible folder in your project path and not under /WEB-INF folder.
Try changing your url-pattern for myservlet to /, and optionally adding <mvc:default-servlet-handler /> (see here) to your Spring configuration.
Removed wrong portion of the answer as per #BalusC comment.
Set a break point in your servlet and perform a debug session. Look for the path that your servlet is picking up these files at. Make sure they match the location

Categories