I'm trying to serve a JSP from Guice. I don't find any basic examples on how to do this!
My setup :
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>org.example.Bootstrap</listener-class>
</listener>
org.example.Bootstrap (something like...)
public class Bootstrap extends GuiceServletContextListener
{
#Override
protected Injector getInjector()
{
return Guice.createInjector(new org.example.BootstrapModule());
}
}
org.example.BootstrapModule (something like...)
public class BootstrapModule extends ServletModule
{
#Override
protected void configureServlets()
{
// serve .JSPs
bind(org.apache.jasper.servlet.JspServlet.class).in(Scopes.SINGLETON);
serveRegex("/.*\\.jsp").with(org.apache.jasper.servlet.JspServlet.class);
// serve my controllers
bind(MainServlet.class).in(Scopes.SINGLETON);
serveRegex("/.*").with(MainServlet.class);
}
}
In MainServlet, I do something like :
request.getRequestDispatcher("test.jsp").include(request, response);
or
request.getRequestDispatcher("test.jsp").forward(request, response);
or
request.getRequestDispatcher("/test.jsp").include(request, response);
or
request.getRequestDispatcher("/test.jsp").forward(request, response);
My test.jsp is in webapp/test.jsp (I use Maven).
It doesn't work! I always end up with errors like :
SEVERE: PWC6117: File XXX not found
It seems the informations Guice passes to org.apache.jasper.servlet.JspServlet are not the ones required for the JSPs to work.
What am I missing? Do I even have to specify org.apache.jasper.servlet.JspServlet manually? What is required to correctly serve JSPs from Guice?
It seems this is a known bug.
As a workaround, some say you can compile the TRUNK of Guice. I also found that setting
request.setAttribute(org.apache.jasper.Constants.JSP_FILE, "/test.jsp");
before the forwarding also works.
But I have to run more tests to see what I'll use until Guice is fixed in a public release.
You need to override Bootstrap#getModule() to return a new BootstrapModule().
#Override
protected Module getModule() {
return new BootstrapModule();
}
Related
I am getting exception com.sai.peps.ejb.frequentexceeding.FrequentExceedingBean cannot be cast to cannot be cast to javax.ws.rs.core.Application
I am using EJB 3.0 and jboss 5.1 & resteasy
Please suggested to me, where is my mistake.
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>resteasy.resources</param-name>
<param-value>com.sai.peps.ejb.frequentexceeding.MyRestApplication</param-value>
</context-param>
<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>com.sai.peps.ejb.frequentexceeding.MyRestApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>resteasy-servlet</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
Edited:
package com.sai.peps.ejb.frequentexceeding;
import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
#ApplicationPath("/rest")
public class MyRestApplication extends Application {
private Set<Object> resourceObjects = new HashSet<Object>();
private Set<Class<?>> resourceClasses = new HashSet<Class<?>>();
public MyRestApplication() {
resourceClasses.add(FrequentExceedingBean.class);
}
#Override
public Set<Class<?>> getClasses() {
return resourceClasses;
}
#Override
public Set<Object> getSingletons() {
return resourceObjects;
}
}
i have added this code.. Still not working
If your class com.sai.peps.ejb.frequentexceeding.FrequentExceedingBean should be the Aplication class as it is configured, it must extend javax.ws.rs.core.Application because the servlet container will instantiate an object of this class and then cast ist to javax.ws.rs.core.Application to be able to call it's getClasses() and getSingletons() method.
Update
Alas JBoss 5.1 has not yet Servlet 3.0., so you cannot confugre it without the web.xml.
Please check the accepted answer of this question for the needed entries in the web.xml file. The configuration is different from yours in respect to where the classnames are. I myself haven't used web.xml configuration for quite a time anymore, so I am not so firm there.
your web.xml seems a little bit messy.
The question is: why should you provide your own implementation fo Application class?
If you have
resteasy.scan = true
you don't need anything else (exept for proper annotations on your Resource and Providers classes to publish your resources).
if you have
resteasy.resources
valued with a list of resources
you can omit the resteasy.scan parameter and explicitly provide a list of resources to be published (in this case you put com.sai.peps.ejb.frequentexceeding.MyRestApplication and it's wrong, probably you should have put com.sai.peps.ejb.frequentexceeding.FrequentExceedingBean)
You may override Application class to move configuration out of web.xml and still have a strict control on the list of resources to be published with custom logic. Are you sure this is your need? If this is the case you should skip above configurations.
In any case choose one of the three methods
Reading the jersey doc : https://jersey.java.net/documentation/latest/entity-filtering.html I was able to activate the SecurityEntityFilteringFeature by adding it to my web.xml along with other activated features.
So my web.xml's features part looks like that :
...
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
org.glassfish.jersey.server.gae.GaeFeature;
org.glassfish.jersey.server.mvc.jsp.JspMvcFeature;
org.glassfish.jersey.media.multipart.MultiPartFeature;
org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
org.glassfish.jersey.message.filtering.SecurityEntityFilteringFeature;
</param-value>
</init-param>
...
The annotations #PermitAll (which changes nothing) and #DenyAll (which always remove entity from json) work great.
The question is : to use the annotation #RolesAllowed I also need to register the roles in the entity-filtering scope as said in the documentation
EntityFilteringFeature.ENTITY_FILTERING_SCOPE - "jersey.config.entityFiltering.scope"
Defines one or more annotations that should be used as entity-filtering scope when reading/writing an entity.
But I can only configure it through my web.xml and I have nowhere to do the following :
new ResourceConfig()
// Set entity-filtering scope via configuration.
.property(EntityFilteringFeature.ENTITY_FILTERING_SCOPE, new Annotation[] {SecurityAnnotations.rolesAllowed("manager")})
// Register the SecurityEntityFilteringFeature.
.register(SecurityEntityFilteringFeature.class)
// Further configuration of ResourceConfig.
.register( ... );
Any guess ?
You can use a ResourceConfig and a web.xml together. It is not "either one or the other". For example
<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.JerseyConfig</param-value>
</init-param>
</servlet>
package org.foo;
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(...);
property(...);
}
}
Both the web.xml and the ResourceConfig registrations/configuration/properties, etc will be used. You can see some other deployment options, here.
If you really must stay away from the ResourceConfig (not sure why it would be such a problem), you can always create a Feature.
#Provider
public class MyFilteringFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.property(...);
context.register(...);
return true;
}
}
Then just register the feature (unless you are scanning packages, then it should be picked up with the #Provider annotation).
I am trying to setup a configurable log4j configuration path for our webapp, so that by default this setting applies:
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/log4j2.xml</param-value>
</context-param>
and if, lets say, some environment variable is defined, then log4j2-test.xml is used. Can I somehow achieve this?
I've tried defining my own listener, which will take care of this, as follows:
web.xml contents:
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>/WEB-INF/log4j2.xml</param-value>
</context-param>
<context-param>
<param-name>isLog4jAutoInitializationDisabled</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>com.bla.blob.listener.Log4j2InitListener</listener-class>
</listener>
And the listener class:
public class Log4j2InitListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
if (System.getProperty("log4j.configurationFile") != null) { //override what is defined in web.xml
ctx.setInitParameter("log4jConfiguration", System.getProperty("log4j.configurationFile"));
}
ctx.addListener(new Log4jServletContextListener());
final FilterRegistration.Dynamic filter = ctx.addFilter("log4jServletFilter",
new Log4jServletFilter());
if (filter != null) {
filter.setAsyncSupported(true);
filter.addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), false, "/*");
}
}
#Override
public void contextDestroyed(ServletContextEvent sce) { }
}
But for some strange reason this solution is not tomcat compatible (though works on jetty) -
java.lang.IllegalArgumentException: Once the first ServletContextListener has been called, no more ServletContextListeners may be added.
at org.apache.catalina.core.ApplicationContext.addListener(ApplicationContext.java:1386)
at org.apache.catalina.core.ApplicationContextFacade.addListener(ApplicationContextFacade.java:659)
Also, apache moved everything webapp related out of core, making everything package private, so you can't fiddle with classes by yourself anymore (yet http://logging.apache.org/log4j/2.x/manual/webapp.html still suggest you can use Log4jWebLifeCycle, for instance).
Any help will be greatly appreciated.
I need to make a custom ExceptionMapper in Jersey to handle the JsonProcessingException returned by Jackson.
The Jackson library already includes ExceptionMapper providers for this exception in the form of JsonMappingExceptionMapper.java and JsonParseExceptionMapper.java (link).
If I add a new provider for this exception mapper in "my.package" I get unpredictable results regarding the selected provider. Sometimes it will select the provider in "my.package" and sometimes it will select the provider in the Jackson library. The code I'm using to scan the packages is below.
PackgesResourceConfig packagesResourceConfig = new PackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");
Proposed Solution
Currently I am getting around this by filtering out the provider in the Jackson library manually. But what I really want to know is whether there is a more acceptable and supported way of doing this.
First I extend PackagesResourceConfig.
public class FilteredPackgesResourceConfig extends PackagesResourceConfig {
private Set<Class<?>> classesToFilter = new HashSet<Class<?>>();
public FilteredPackgesResourceConfig(String... packages) {
super(packages);
}
public FilteredPackgesResourceConfig(Map<String, Object> props) {
super(props);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> classes = super.getClasses();
if (classes != null && classesToFilter != null) {
classes.removeAll(classesToFilter);
}
return classes;
}
public Set<Class<?>> getClassesToFilter() {
return classesToFilter;
}
public void setClassesToFilter(Set<Class<?>> classesToFilter) {
this.classesToFilter = classesToFilter;
}
}
This I use this class to filter out the specific providers I don't want.
FilteredPackgesResourceConfig packagesResourceConfig = new FilteredPackgesResourceConfig("com.fasterxml.jackson.jaxrs", "my.package");
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonMappingExceptionMapper.class);
classesToFilter.add(com.fasterxml.jackson.jaxrs.json.JsonParseExceptionMapper.class);
packagesResourceConfig.setClassesToFilter(classesToFilter);
This solution gives me the desired result of only using the providers I specified.
Is there a more correct way of achieving the same result?
I also came across this problem, in my case I solved it by instead of registering com.fasterxml.jackson.jaxrs.json package I only registered the class I wanted, which in my case was com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider.
There are several ways to do this, I did it using web.xml like so:
<servlet>
<servlet-name>jersey-serlvet</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>
my.own.package
my.other.package
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.server.provider.classnames</param-name>
<param-value>
com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider
</param-value>
</init-param>
<init-param>
<param-name>jersey.config.disableMoxyJson</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Note: I'm using Jersey 2.0, in 1.x the property names and servlet class are diferent but the same config is possible.
I have the same requirement, where I have to use the custom ExceptionMapper which implements ExceptionMapper<Exception> for all Exception types. Unfortunately, Jersey by default registers org.glassfish.jersey.jackson.JacksonFeature if the dependency jersey-media-json-jackson present in the classpath which inturn registers JsonParseExceptionMapper and JsonMappingExceptionMapper automatically and due to this default mechanism these default JSON exception mappers receives all JSON related exceptions, that is the reason the custom exception mapper is not invoked particularly for JSON exceptions.
Fortunately, Jersey 2.29.1 added support for registering JacksonFeature without the exception handlers. link feature request link, code changes.
Therefore we have to override the default JacksonFeature by excluding the exception mappers as below
#Provider
public class ApplicationInitializer extends ResourceConfig {
public ApplicationInitializer() {
register(JacksonFeature.withoutExceptionMappers());
}
}
Hi guys with my question. A GWT project, as i have read Gin i usable only on the client side than Guice is usable on the server side. Here is my question.
Let first post some example code.
Server side.
public class WebchargeServiceImpl extends RemoteServiceServlet implements WebchargeService
{
#Inject
private Injector injector;
#Inject
private ExecuteOperations executeOperations;
.....
executeOperations.do(); ....
Here is the injected class ExecuteOperations
#Singleton
public class ExecuteOperations
{
.........
}
Also i have servlet module class
public class SampleWebGuiceServletConfig extends GuiceServletContextListener
{
#Override
protected Injector getInjector()
{
return Guice.createInjector(Stage.DEVELOPMENT, new SampleWebModule());
}
} // class
.....
public class SampleWebModule extends ServletModule
{
#Override
protected void configureServlets()
{
bind(WebchargeServiceImpl.class); //is it correct to bind a class like that?
} // class
web.xml
<servlet>
<servlet-name>.......WebchargeService</servlet-name>
<servlet-class>.....WebchargeServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>.........WebchargeService</servlet-name>
<url-pattern>/Webcharge/WebchargeService</url-pattern>
</servlet-mapping>
<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>......SampleWebGuiceServletConfig</listener-class>
</listener>
</web-app>
I'm missing something because i get null every time, this code works ok in servlet/jsp env but here...
Advice place.
Thanks.
You have to map your WebchargeServiceImpl servlet in your SampleWebModule, not in your web.xml; otherwise it'll be constructed by your servlet container and not by Guice, so it won't be "injected".
How do your servlets get instantiated? Did you install the Guice Servlet Filter?