how to restrict the access to service in different modules - java

My requirement is to call the services from two different modules.But, Some urls can allow both modules,some urls allow for specific to that module.
Below is my current configuration for achieving that
<servlet>
<servlet-name>animals</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.lion,com.dog</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/lion/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>animals</servlet-name>
<url-pattern>/dogs/*</url-pattern>
</servlet-mapping>
For example if I have a service called as 'barking' this service is located in com.dog package.Now i can call this service using two urls like below
/lions/barking
/dogs/barking
As per my requirement /lions/barking should show 404 error.But it gives the response.
But some url both should work.Irrespective of where the service is located.
/lions/eat
/dogs/eat
How to do the configuration to achieve that functionality
Any help will be greatly appreciated!!!!

Use a "http Servlet Request Filter" to customise and configure/serve the requests as per your business requirements.
Please find the sample code below:
public class RequestUrlFilter implements Filter {
private static List<String> validUrls = new ArrayList<>();
public void init(FilterConfig filterConfig) throws ServletException {
//Load the valid list of urls here
validUrls.add("/lions/eat");
validUrls.add("/dogs/eat");
validUrls.add("/dogs/barking");
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain)
throws IOException, ServletException {
if(validUrls.contains(((HttpServletRequest)request).getRequestURI()) {
filterChain.doFilter(request,response);
} else {
//Error Response
RequestDispatcher rd = (HttpServletRequest)request.getRequestDispatcher("Error.jsp");
rd.forward(request, response);
}
}
public void destroy() {
}
}

Related

HTTP 302 when Google Drive API sends push notifications

I just managed to call the Google Drive API to enable push notifications for a file.
The code setting up the push notifications look like this:
public class SampleServlet extends AbstractAppEngineAuthorizationCodeServlet {
private final static Logger logger = Logger.getLogger(SampleServlet.class.getName());
private static final long serialVersionUID = 1L;
// Constants omitted
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException, ServletException {
AuthorizationCodeFlow authFlow = initializeFlow();
Credential credential = authFlow.loadCredential(getUserId(req));
StringBuilder resultFromWatch = new StringBuilder();
Drive drive = new Drive.Builder(Utils.HTTP_TRANSPORT, Utils.JSON_FACTORY, credential).setApplicationName("t").build();
try {
Optional<Channel> channel = watchFile(drive, FILE_ID, CHANNEL_ID, "web_hook", "https://mydomain.appspot.com/drive");
String channelStringTmp;
if (channel.isPresent()) {
channelStringTmp = channel.get().toString();
} else {
channelStringTmp = "null...";
}
resultFromWatch.append(channelStringTmp);
} catch (Exception e) {
resultFromWatch.append(e.getMessage());
}
final UserService userService = UserServiceFactory.getUserService();
final String thisUrl = req.getRequestURI();
// Send the results as the response
PrintWriter respWriter = resp.getWriter();
resp.setStatus(200);
resp.setContentType("text/html");
addLoginLogoutButtons(req, resp, resultFromWatch, userService, thisUrl, respWriter);
}
private static Optional<Channel> watchFile(Drive service, String fileId,
String channelId, String channelType, String channelAddress) throws IOException {
final Channel returnValue;
Channel channel = new Channel();
channel.setId(channelId);
channel.setType(channelType);
channel.setAddress(channelAddress);
Drive.Files tmp = service.files();
returnValue = tmp.watch(fileId, channel).execute();
return Optional.fromNullable(returnValue);
}
#Override
protected AuthorizationCodeFlow initializeFlow() throws ServletException, IOException {
return Utils.initializeFlow();
}
#Override
protected String getRedirectUri(HttpServletRequest req) throws ServletException, IOException {
return Utils.getRedirectUri(req);
}
}
After having called the servlets doGet from my browser and logging in I get this as response:
{
"expiration": "1484565747000",
"id": SAME_ID_AS_DEFINED_IN_SERVLET,
"kind": "api#channel",
"resourceId": A_NEW_ID,
"resourceUri": "https:\/\/www.googleapis.com\/drive\/v3\/files\/FILE_ID?acknowledgeAbuse=false&alt=json"
}
Next step is to define my controller that receives notifications when the file is modified. Looks like this:
#RestController
#RequestMapping("/drive")
public class ConcreteFileWatchController implements FileWatchController {
private final static Logger logger = Logger.getLogger(ConcreteFileWatchController.class.getName());
#RequestMapping(method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.OK)
#Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
logger.info("Received watch call");
}
}
Finally I try to modify the file after having deployed the application(it is deployed on Google App Engine) and after looking at the logs in GAE I can see that there has been a call. However, my receiving method is not executed. I only see a 302 in the log with a big json attached to it. Can't really see any error except that I don't notice that my method is called. The path even looks correct in the log. What could I be doing wrong?
Details regarding error:
When I go to the log page in Google Cloud I see this 302 message:
11:34:35.957
POST
302
0 B
22 ms
APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)
/drive
10.72.94.97 - - [16/Jan/2017:11:34:35 +0100] "POST /drive HTTP/1.1" 302 - - "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)" "mydomain.appspot.com" ms=22 cpu_ms=0 cpm_usd=0 loading_request=0 instance=- app_engine_release=1.9.48 trace_id=d0e888dd3989e353344e40e41758fdf4
There is also a json looking kind of like this:
{
protoPayload: {
#
type: "type.googleapis.com/google.appengine.logging.v1.RequestLog"
appId: "p~blabla"
versionId: "201t113050"
requestId: "587ca1bb00ff05706f727465726261636b656e640001323031373031313674313133303530000100"
ip: "10.76.94.97"
startTime: "2017-01-16T10:34:35.957904Z"
endTime: "2017-01-16T10:34:35.980366Z"
latency: "0.022462s"
method: "POST"
resource: "/drive"
httpVersion: "HTTP/1.1"
status: 302
userAgent: "APIs-Google; (+https://developers.google.com/webmasters/APIs-Google.html)"
host: "blabla.appspot.com"
instanceIndex: -1
finished: true
appEngineRelease: "1.9.48"
traceId: "d0e888dd390f41758fdf4"
first: true
}
insertId: "587cf6df9ded23f7"
httpRequest: {
status: 302
}
resource: {
type: "gae_app"
labels: {…}
}
timestamp: "2017-01-16T10:34:35.957904Z"
labels: {
appengine.googleapis.com/version_id: "2017013050"
clone_id: ""
appengine.googleapis.com/clone_id: ""
appengine.googleapis.com/module_id: "default"
version_id: "20170116t113050"
request_id: "587ca1bb00ff0e9dd0f39f31350001707e6561737974696d657265706f721373031313674313133303530000100"
appengine.googleapis.com/request_id: "587ca1bb00ff0e9dd0f39f31350001707e6561737974696d6572653674313133303530000100"
module_id: "default"
}
logName: "projects/blabla/logs/appengine.googleapis.com%2Frequest_log"
operation: {
id: "587ca1bb00ff0e9dde640001323031373031313674313133303530000100"
producer: "appengine.googleapis.com/request_id"
first: true
last: true
}
}
web.xml:
<web-app>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/mvc-dispatcher-servlet.xml</param-value>
</context-param>
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>PlusBasicServlet</servlet-name>
<servlet-class>packagename.PlusBasicServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PlusBasicServlet</servlet-name>
<url-pattern>/plusbasicservlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PlusSampleServlet</servlet-name>
<servlet-class>packagename.PlusSampleServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PlusSampleServlet</servlet-name>
<url-pattern>/plussampleservlet</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>FileWatchTestServlet</servlet-name>
<servlet-class>packagename.ConcreteFileWatchController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileWatchTestServlet</servlet-name>
<url-pattern>/drive</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>PlusSampleAuthCallbackServlet</servlet-name>
<servlet-class>packagename.PlusSampleAuthCallbackServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>PlusSampleAuthCallbackServlet</servlet-name>
<url-pattern>/oauth2callback</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>any</web-resource-name>
<url-pattern>/plussampleservlet</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>
</web-app>
Screenshot from log:
Since your callback is being served through Spring MVC, make sure you don't have any hidden redirects configured elsewhere. You should first test the callback using a regular servlet:
public class FileWatchTestServlet extends HttpServlet {
private final static Logger logger = Logger.getLogger(FileWatchTestServlet.class.getSimpleName());
#Override
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
logger.info("Received watch call");
}
}
And in web.xml:
<servlet>
<servlet-name>FileWatchTestServlet</servlet-name>
<servlet-class>com.mydomain.FileWatchTestServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>FileWatchTestServlet</servlet-name>
<url-pattern>/drive</url-pattern>
</servlet-mapping>
If the 302 goes away, the issue is with Spring MVC's dispatcher, so you should look there for anything that might cause a redirect (eg. in your view).

my servlet mapping spoil my filter

In my program any url in the form of /Controller/* is redirected by my servlet mapping to Controller class.
I tried to add a filter for authantication, if user is not logged in and path is not /Controller/RegForm it's redirecting to /Controller/RegForm.
Problem is because my servlet mapping redirects to /Controller, filter always gets the /Controller as path.
How can I use both filter and the servlet mapping ?
This is my web.xml:
<filter>
<filter-name>AuthFilter</filter-name>
<filter-class>AuthFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthFilter</filter-name>
<url-pattern>/Controller/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>Controller</servlet-name>
<servlet-class>Controller</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Controller</servlet-name>
<url-pattern>/Controller/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
my filter:
#WebFilter("/Controller/*")
public class AuthFilter implements Filter {
#Override
public void init(FilterConfig config) throws ServletException {
// If you have any <init-param> in web.xml, then you could get them
// here by config.getInitParameter("name") and assign it as field.
}
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String path = ((HttpServletRequest) request).getServletPath();
if ((session != null && session.getAttribute("student") != null )||(excludeFromFilter(path))) {
chain.doFilter(req, res); // Log
}
else {
response.sendRedirect("/registration-war/Controller/RegForm"); // No logged-in user found, so redirect to login page.
}
}
private boolean excludeFromFilter(String path) {
if (path.equals("/Controller/RegForm")) {
return true; // add more page to exclude here
} else {
return false;
}
}
You use HttpServletRequest.getServletPath() which returns the servlet URL which is (according to your servlet mapping) "/Controller".
You want the path info not the servlet path:
Returns any extra path information associated with the URL the client sent when it made this request. The extra path information follows the servlet path but precedes the query string and will start with a "/" character.
So for example this will return "/RegForm" if your user requests the /Controller/RegForm page.
String pathInfo = HttpServletRequest.getPathInfo();

Best way to catch all unhandled exceptions in all Tomcat (GWT) servlets

I use Tomcat 7 and Lo4j for all my server logs and GWT for client (only AJAX calls).
All my unhandled exceptions get logged in my catalina.log.
Now I want to catch all exceptions and add some of the user's specific Tomcat SessionData.
There are several ways:
Try catch over all servlets (there must be a better solution).
http://tomcat.apache.org/tomcat-7.0-doc/aio.html: I would have to change my connecter, and I don't know if I could use the Tomcat Session within the Event Handler (EventType.ERROR).
Better way?
What would be the best way to achieve this?
Out of what I understood from your question, you can try to use at least one of two ways:
Basic Logging Servlet
If you have access to the source code of all of your servlets, you can make a little refactoring using a basic super-servlet that is responsible for the logging/whatever of every request working transparently with AJAX, no error forwards directives, and no global exception handlers. Suppose you use service(ServletRequest,ServletResponse) as the servlet entry point (but you can do the following for every do*() method either), then you can create an abstract super-servlet and simply inherit your servlets from it.
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>stackoverflow.Servlet1</servlet-class>
</servlet>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>stackoverflow.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>servlet1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>servlet2</url-pattern>
</servlet-mapping>
public abstract class BasicServlet extends HttpServlet {
/**
* Won't let it be {#code abstract} - we don't want to force any sub-servlet to implement this method.
*/
protected void doService(ServletRequest request, ServletResponse response) {
}
#Override
public final void service(ServletRequest request, ServletResponse response) {
try {
doService(request, response);
} catch ( Throwable ex ) {
err.println(ex.getMessage());
}
}
}
public final class Servlet1 extends BasicServlet {
#Override
protected void doService(ServletRequest request, ServletResponse response) {
out.println("I'm servlet #1");
}
}
public final class Servlet2 extends BasicServlet {
#Override
protected void doService(ServletRequest request, ServletResponse response) {
out.println("I'm servlet #2");
}
}
An advantage of this method is that you do not need to configure anything else than changing your servlet classes and not depend on the external configuration or context. The disadvantage is that you always must extend BasicServlet.
Filter
I didn't actually test it right now, for more information please see http://docs.oracle.com/javaee/6/api/javax/servlet/Filter.html . Filters allow to intercept each request (we use such a filter implementation for our JSPs while debugging and writing the exceptions into the common log file). The disadvantage is that it's not guaranteed that the filter can cover every exception/case, for example if any filter preceded your own filter.
<filter>
<filter-name>exceptionLoggingFilter</filter-name>
<filter-class>stackoverflow.ExceptionLoggingFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>exceptionLoggingFilter</filter-name>
<url-pattern>*</url-pattern> <!-- we will process every request -->
</filter-mapping>
public final class ExceptionLoggingFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
try {
filterChain.doFilter(request, response);
} catch ( Throwable ex ) {
err.println(ex);
}
}
#Override
public void destroy() {
}
}
Hope this helps.
Just Overriding the GWT function doUnexpectedFailure worked.
#Override
protected void doUnexpectedFailure(Throwable t) {
ServerLog.error(t.getMessage(), t);
super.doUnexpectedFailure(t);
}
1) You can define error page for your webapp, like this:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error</location>
</error-page>
Then you can bind another servlet at /error and handle the exception there.
2) You can setUncaughtExceptionHandler for every HTTP connector thread. You could use this technique with servlet filter which would contain reference to the current HttpRequest (say, via a thread local). This won't work with async I/O by the way.

Filter called only for servlets

How can i use a Filter just for servlets and not for jsp?
url-patterns :
/* - this makes the container to call the filter for servlets as well as jsp.
*.jsp - this makes the container to call the filter only for jsp.
Is there any way it calls the filter only for servlets..
Since filter is mapped to URL and the mapping is always "positive", i.e. you cannot say "call this filter unless url is *.jsp) the only solution is create special URLs for either servlets or JSPs.
For example you can map all your servlets to URLs that end with *.do, e.g. create.do, delete.do etc.
<servlet-mapping>
<servlet-name>Create Servlet</servlet-name>
<url-pattern>/create.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Delete Servlet</servlet-name>
<url-pattern>/delete.do</url-pattern>
</servlet-mapping>
Then you can create filter and map it to *.do:
<filter-mapping>
<filter-name>actionsFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
It will work for all servlets (because they are mapped to *.do) and will not work for JSPs (because they are not mapped to *.do).
You can do this by adding a Dummy Filter that doesn't propagate to the FilterChain, i.e. not calling FilterChain.doFilter() in the Dummy Filter, but including the requestdispatcher for jsp files.
public class NOPDummyFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
req.getRequestDispatcher(req.getServletContext().getContextPath()
.substring(req.getServletContext().getC‌​ontextPath().lastIndexOf('/') + 1)).include(request, response);
}
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
}
and in the web.xml:
<filter>
<filter-name>NOPDummyFilter</filter-name>
<filter-class>NOPDummyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>NOPDummyFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>MyRealServletFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
see this discussion: http://www.coderanch.com/t/169859/java-Web-Component-SCWCD/certification/Filter-has-Exclude-url-pattern
hope this helped.
And code:
// Check if request goto a Servlet
private boolean needFilter(HttpServletRequest request) {
//
// Servlet Url-pattern: /path/*
//
// => /path
String servletPath = request.getServletPath();
// => /abc/mnp
String pathInfo = request.getPathInfo();
String urlPattern = servletPath;
if (pathInfo != null) {
// => /path/*
urlPattern = servletPath + "/*";
}
// Key: servletName.
// Value: ServletRegistration
Map<String, ? extends ServletRegistration> servletRegistrations = request.getServletContext()
.getServletRegistrations();
// collection of all servlets in your webapp.
// containing *.jsp & *.jspx
Collection<? extends ServletRegistration> values = servletRegistrations.values();
for (ServletRegistration sr : values) {
Collection<String> mappings = sr.getMappings();
if (mappings.contains(urlPattern)) {
return true;
}
}
return false;
}

Routing request to matching pages using guice servlets

I am developing inherited jsp/java ee application and I would like to introduce Guice IoC container to my application. However, I found some obstacles. I can't translate web.xml entries into guice registrations if there are more then one routing to single servlet using different urls. Problem is with init-parameters.
Here are some extracts from my web.xml:
This one is unrelated to problem, but it is good example how we are using init parameters. Basically it maps users with different roles in systems to appropriate pages.
<!-- LIST INTERNSHIPS SERVLET -->
<servlet>
<servlet-name>ListInternships</servlet-name>
<servlet-class>pl.poznan.put.ims.controllers.ListInternships</servlet-class>
<init-param>
<param-name>CoordinatorPage</param-name>
<param-value>WEB-INF/pages/coordinator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>MentorPage</param-name>
<param-value>WEB-INF/pages/mentor/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AdministratorPage</param-name>
<param-value>WEB-INF/pages/administrator/listinternships.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>Coordinator, Mentor, Administrator</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ListInternships</servlet-name>
<url-pattern>/internships</url-pattern>
</servlet-mapping>
Those two are the troublesome ones:
<!-- CHANGE PASSWORD SERVLET -->
<servlet>
<servlet-name>ChangePassword</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/shared/password.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>ChangePassword</servlet-name>
<url-pattern>/changepassword</url-pattern>
</servlet-mapping>
<!-- HELP SERVLET -->
<servlet>
<servlet-name>Help</servlet-name>
<servlet-class>myapp.controllers.ContextForwarder</servlet-class>
<init-param>
<param-name>SharedPage</param-name>
<param-value>WEB-INF/pages/help/help.jsp</param-value>
</init-param>
<init-param>
<param-name>AllowedRoles</param-name>
<param-value>*</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Help</servlet-name>
<url-pattern>/help</url-pattern>
</servlet-mapping>
Here is my servlet:
#Singleton
public class ContextForwarder extends HttpServlet {
private static final long serialVersionUID = 1L;
private final IUserDao dao;
#Inject
public ContextForwarder(IUserDao dao) {
this.dao = dao;
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//trying to get rid of statics, using Ioc
Validator.checkUserLoggedIn (request);
Validator.checkUserAuthorized(this, request);
User currentUser = UserManager.getCurrentUser(request);
//pick matching page for user
String userViewPage = ServletUtils.getUserURL(this, currentUser, "Page");
try {
dao.openSession();
dao.beginTransaction();
currentUser = UserManager.reloadCurrentUser(request, dao);
ServletUtils.forward(request, response, userViewPage);
dao.commit();
}
catch(ServletException e) {
dao.rollback();
throw e;
}
catch(Exception e) {
dao.rollback();
throw new ServletException(e);
}
finally {
dao.closeSession();
}
}
}
public class ServletUtils {
public static void forward(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
RequestDispatcher view = request
.getRequestDispatcher( response.encodeRedirectURL(location) );
view.forward(request, response);
}
public static String getUserParameter(GenericServlet servlet, User user, String suffix) {
return servlet.getInitParameter( user.getRoles() + suffix );
}
public static String getUserURL(GenericServlet servlet, User user, String suffix)
throws ResourceNotFoundException {
String URL = getUserParameter(servlet, user, suffix);
if(URL == null) {
URL = servlet.getInitParameter("Shared" + suffix);
if(URL == null)
throw new ResourceNotFoundException(suffix);
}
return URL;
}
public static void redirect(HttpServletRequest request, HttpServletResponse response, String location)
throws ServletException, IOException {
response.sendRedirect( response.encodeRedirectURL(location) );
}
}
When i try to translate it into guice (and then register this module):
public class MyServletModule extends ServletModule
{
#Override
protected void configureServlets() {
configureHelp();
configurePassword();
}
private void configureHelp()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/help.jsp");
params.put("AllowedRoles", "*");
serve("/help").with(ContextForwarder.class, params);
}
private void configurePassword()
{
Map<String, String> params = new HashMap<String, String>();
params.put("SharedPage", "WEB-INF/pages/shared/password.jsp");
params.put("AllowedRoles", "*");
// it's routing correctly to servlet, but it uses params from first registration,
// so that routing to jsp page is incorrect
serve("/changepassword").with(ContextForwarder.class, params);
}
}
The problem is that guice creates ContextForwarder servlet as a singleton with init parameters from the first registered method and then regardless of the request url it has parameters from the first registration. Is there any other solution to route user to different sites considering current user role? Is it possible to configure the same servlet class with two different configurations?
I have found a solution, however I am not fully satisfied with it. I found out that, in solution without guice, web container (tomcat) creates two separate servlets using the same servlet class and injecting different init parameters. Guice by default restricts servlets to be singletons, so to copy default behaviour from web.xml solution I needed to find a way to create two instance of the same class and register it twice with different parameters. I solved this by creating two sub-classes to my servlet class, both with empty body, then I registered them with different parameters.
This solution works, but it involve creating empty-body sub-classes which I am not satisfied with. It's not a problem when I got two sub-classes, but with more of them code is becoming cumbersome.

Categories

Resources