I create guice servlet like this:
public class GuiceApplicationServlet extends AbstractApplicationServlet {
protected Provider<Application> applicationProvider;
public GuiceApplicationServlet() {
System.out.println("TTest");
}
#Inject
public GuiceApplicationServlet(Provider<Application> applicationProvider) {
super();
this.applicationProvider = applicationProvider;
System.out.println("Test");
}
#Override
protected Class<? extends Application> getApplicationClass()
throws ClassNotFoundException {
return Application.class;
}
#Override
protected Application getNewApplication(HttpServletRequest request)
throws ServletException {
return applicationProvider.get();
}
}
web.xml:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>pl.koziolekweb.vaadin.guice.servlet.VaadinGuiceConfiguration</listener-class>
</listener>
<servlet>
<servlet-name>Vaadin Application Servlet</servlet-name>
<servlet-class>pl.koziolekweb.vaadin.guice.servlet.GuiceApplicationServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Vaadin Application Servlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The problem is that when I run jetty then Guice create instance of servlet (print "Test" in console) but when I try to run application in browser i get NPE and in console "TTest" appear.
So jetty create another instance of servlet that is not managed by guice.
Question is how to configure jetty to use only guice?
You have to create a guice servlet module which extends com.google.inject.servlet.ServletModule (let's call it FooModule). You define there your bindings and paths to servlets by overriding configureServlets() method.
Then you must create context listener by extending com.google.inject.servlet.GuiceServletContextListener (let's call it BarContextListener). There you must implement getInjector() method, with something like that:
protected Injector getInjector() {
Injector injector = Guice.createInjector(new FooModule());
return injector;
}
Then you remove all servlet mappings from your web.xml, and then put filter:
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
and context listener You created:
<listener>
<listener-class>path.to.package.of.context.listener.BarContextListener</listener-class>
</listener>
By this all Your servlets are managed by Guice and enable dependency injection in server side of Your application. It works for me in Tomcat so it should also work on Jetty. Don't forget to include guice-servlet-<version>.jar into your classpath. I didn't use it with Vaadin, but I guess my answer helped You little bit.
Because Guice should create all your Servlet instances, you have to remove the servlet and servlet-mapping entries from your web.xml file.
I have written a blog post on the subject, I'm sure it would be most helpful :
Vaadin + GAE + Guice-Servlet - TUTORIAL
Related
I have a Spring filter in the XML format provided below,
<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I load it as an XML file in the top of the class. Will it be possible to write Java instead of the XML definition?
In case of Spring you should define a class that extends AbstractDispatcherServletInitializer and add following lines to it
#Override
protected Filter[] getServletFilters() {
return new Filter[] {
new OpenEntityManagerInViewFilter();
};
}
You can get more information about filters in Java code from Spring Docs
https://docs.spring.io/spring/docs/4.1.1.RELEASE/spring-framework-reference/html/mvc.html#mvc-container-config
web.xml:
<filter>
<filter-name>myFilter</filter-name>
<filter-class>com.mypackage.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/myFilterPattern/*</url-pattern>
</filter-mapping>
MyFilter:
public class MyFilter implements Filter {
#Autowired
InjectedBean someInjectedBean;
However, when intercepting /myFilterPattern/* requests, someInjectedBean in MyFilter.doFilter(...) is still null, meaning it has not been injected. The same bean (InjectedBean) is injected fine in other context components that are not referenced in web.xml.
Is it because container filtering takes place outside the Spring context? Is there any way to have Spring injection in Filter implementation mapped in web.xml?
Since Filter is not a spring bean(it is a web component) the injections won't work inside them. Springs wont inject inside web component.
use a DelegatingFilterProxy, this is a filter implementation that takes a springbean name as init param and delegates the filter request to that bean.
<filter>
<filter-name>myFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>myFilterBean</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/myFilterPattern/*</url-pattern>
</filter-mapping>
And create a Bean with name myFilterBean in your spring context.
public class MyFilter extends GenericFilterBean {
#Autowired
InjectedBean someInjectedBean;
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(request, response);
}
}
One more solution if you are using spring security and extending the OncePerRequestFilter
#Component
public class CustomAuthorizationFilter extends OncePerRequestFilter{
#Autowired
ResourceConfig resourceConfig;
public CustomAuthorizationFilter() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}
//...your code
its important to pull the details from resourceConfig in doFilterInternal block only so you will get values else you may end up at null pointer exception.
I have two separate handfuls of REST services in one application. Let's say a main "people" service and a secondary "management" service. What I want is to expose them in separate paths on the server. I am using JAX-RS, RESTEasy and Spring.
Example:
#Path("/people")
public interface PeopleService {
// Stuff
}
#Path("/management")
public interface ManagementService {
// Stuff
}
In web.xml I currently have the following set-up:
<listener>
<listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
</listener>
<listener>
<listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/public</param-value>
</context-param>
<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>/public/*</url-pattern>
</servlet-mapping>
The PeopleService and ManagementService implementations are just Spring beans.
Above web.xml configuration will expose them both on /public (so having /public/people and /public/management respectively).
What I want to accomplish is to expose the PeopleService on /public, so that the full path would become /public/people and expose the ManagementService on /internal, so that its full path would become /internal/management.
Unfortunately, I cannot change the value of the #Path annotation.
How should I do that?
actually you can. After few hours of debugging I came up with this:
1) Declare multiple resteasy servlets in your web.xml (two in my case)
<servlet>
<servlet-name>resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/openrest</param-value>
</init-param>
<init-param>
<param-name>resteasy.resources</param-name>
<param-value>com.mycompany.rest.PublicService</param-value>
</init-param>
</servlet>
<servlet>
<servlet-name>private-resteasy-servlet</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/protectedrest</param-value>
</init-param>
<init-param>
<param-name>resteasy.resources</param-name>
<param-value>com.mycompany.rest.PrivateService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>private-resteasy-servlet</servlet-name>
<url-pattern>/protectedrest/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/openrest/*</url-pattern>
</servlet-mapping>
Please pay attention to the fact that we initialize personal resteasy.servlet.mapping.prefix and resteasy.resources for each our servlet.
Please don't forget to NOT include any botstrap classes as filters or servlets! And disable autoscan as well.
2) Create a filter that cleans up application from the RESTeasy's global information that it saves in context:
public class ResteasyCleanupFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// TODO Auto-generated method stub
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
ServletException {
request.getServletContext().setAttribute(ResteasyProviderFactory.class.getName(), null);
request.getServletContext().setAttribute(Dispatcher.class.getName(), null);
chain.doFilter(request, response);
}
#Override
public void destroy() {
// TODO Auto-generated method stub
}
}
Register it for any request to your services (here I used it for all requests for simplisity):
<filter>
<filter-name>CleanupFilter</filter-name>
<filter-class>com.mycompany.ResteasyCleanupFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CleanupFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Thats it!Now you have two different REST services which lays under different prefixes : /openrest which meant to service all public requests and /protectedrest that takes care about all the private stuff in the app.
So why does it work (or why it does not work otherwise)?
When you call openrest instance for the first time it tries to initalize itself and when done saves the state in the global servletContext like this :
servletContext.setAttribute(ResteasyProviderFactory.class.getName(), deployment.getProviderFactory());
servletContext.setAttribute(Dispatcher.class.getName(), deployment.getDispatcher());
And if you will let it be your call to your second /protectedrest will get the SAME configuration! That is why you need to clean up this information some where. That is why we used our CleanupFilter which empty the context so brand new rest servlet could initialize itself with all the init parameters we declared.
This is a hack, but it does the trick.
This solution was tested for RESTEasy 2.3.6
EDITED
Works with 3.0.9.final as well!
AFAIK, you cannot have multiple servlet mappins for your JAX-RS implementation.
What you could do is: map RESTEasy to '/' (or '/api' for example if your application has other resources to serve and you don't want the JAX-RS part to interfere), then have the following #Path annotations:
#Path("/public/people")
public interface PeopleService {
// Stuff
}
#Path("/internal/management")
public interface ManagementService {
// Stuff
}
I am trying to run two Servlet-class in a single web.xml but its not working, each servlet-class works fine independently.
web.xml:
<servlet>
<servlet-name>spring-ws</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring-ws</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>240</session-timeout>
</session-config>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-ws-servlet.xml
/WEB-INF/health-page-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>health-page</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>health-page</servlet-name>
<url-pattern>/health.htm</url-pattern>
</servlet-mapping>
Do let me know if you can figure something wrong that i am doing.
I tried the below link but it doesnt work for me
Can I use Spring MVC and Spring WS in one single application?
This isn't going to work. The one which is mapped on /* overtakes all requests. You need to map it on / instead so that it will only intercept on requests which are not matched by all other existing servlets (including the JSP servlet which is implicitly mapped on *.jsp and all "normal" static resources like CSS/JS/image files!). See also Difference between / and /* in servlet mapping url pattern.
If being able to serve static resources is also required, then better map it on a more specific URL pattern like /ws/* and create a Filter which checks the request URI and then forwards accordingly. That filter can in turn safely be mapped on /*. See also this answer for a more concrete code example: How to access static resources when mapping a global front controller servlet on /*.
I am using Java configuration in my project and following code works fine for the same purpose:
public class Initializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ApplicationConfiguration.class);
ctx.setServletContext(servletContext);
MessageDispatcherServlet messageDispatcherServlet = new MessageDispatcherServlet();
messageDispatcherServlet.setApplicationContext(ctx);
messageDispatcherServlet.setTransformWsdlLocations(true);
Dynamic dynamic = servletContext.addServlet("messageDispatcherServlet", messageDispatcherServlet);
dynamic.addMapping("/ws/*");
dynamic.setLoadOnStartup(1);
dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
}
}
you have a mapping for /* in the spring-ws section which is getting the request. you need to
come up with a different strategy... Try putting the /health.htm before the /* mapping.
I'm looking to use pretty / clean URL's in my web app.
I would like the following URL:
http://mydomain.com/myapp/calculator
.. to resolve to:
com.mydomain.myapp.action.CalculatorActionBean
I tried overwriting the NameBasedActionResolver with:
public class CustomActionResolver extends NameBasedActionResolver {
public static final String DEFAULT_BINDING_SUFFIX = ".";
#Override
protected String getBindingSuffix() {
return DEFAULT_BINDING_SUFFIX;
}
#Override
protected List<String> getActionBeanSuffixes() {
List<String> suffixes = new ArrayList<String>(super.getActionBeanSuffixes());
suffixes.add(DEFAULT_BINDING_SUFFIX);
return suffixes;
}
}
And adding this to web.xml:
<servlet-mapping>
<servlet-name>StripesDispatcher</servlet-name>
<url-pattern>*.</url-pattern>
</servlet-mapping>
Which gets me to:
http://mydomain.com/myapp/Calculator.
But:
A stray "." is still neither pretty nor clean.
The class name is still capitalized in the URL..?
That still leaves me with *.jsp..? Is it even possible to get rid of both .action and .jsp?
I think you are looking for the #URLBinding annotation. Look at #URLBinding on your Bean.
#UrlBinding("/calculator")
Try to use DMF
http://stripes.sourceforge.net/docs/current/javadoc/net/sourceforge/stripes/controller/DynamicMappingFilter.html
I was trying to do the same thing, and had the same question, though I wanted my URL to use the trailing slash http://mydomain.com/myapp/calculator/
The answer is to use #UrlBinding & the DynamicMappingFilter
I modified the example to have:
#UrlBinding("/calculator/")
public class CalculatorActionBean implements ActionBean {
.
.
.
return new ForwardResolution("/WEB-INF/view/calculator.jsp");
Then I added the DMF to web.xml:
<filter>
<display-name>Stripes Dynamic Mapping Filter</display-name>
<filter-name>DynamicMappingFilter</filter-name>
<filter-class>net.sourceforge.stripes.controller.DynamicMappingFilter</filter-class>
<init-param>
<param-name>ActionResolver.Packages</param-name>
<param-value>com.example.stripes</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>DynamicMappingFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>
Now the clean URL works as expected, and I'm never redirected to a *.action URL after interacting with the form.