3

I have a web application with multiple WARS. These WARS all perform different functions but have many things in common : Css, Js, headers and footers, and certain jsps to output error messages and confirmations of transactions. For good maintainabilty I dont want to have any of these shared files in multiple locations, rather, one location so If I make an edit to one, it shows up in all. Just basic code management stuff, I don't think I really need to explian this to anyone here on SO.

For Css and Js, I have a root War and I just absolutely address all of the <link> and <script> tags to it. For Headers and Footers (jsp fragments) I am using <c:import> and am grabing again from the root war. The final problem I have is shared jsps.

I often forward to these jsps after a user tries to perfrom an action which results in a change to our database to confirm that the transaction was completed or in other situations where I want to give formatted messages to the user. A Servlet might look like this...

public class sampleServlet extends ExtendedHttpServlet{ //ExtendedHttpServlet used to add common function to all of our HttpServlets including the foward function I use below. 
     public void doPost(HttpServletRequest request, HttpServletResponse response){

        //Do some preperation stuff here, then...

        try{

            ModelJob.insertNewControlMJob(user, submit);  //ModelJob is my inteface to our 'Job' Table Model... 
            submit.setSeqId(ModelJob.getSeqId(user, submit));
            EmailFactory.SUBMIT_NEW_EMAIL.sendCMAdminEmail(user, submit, null);
            EmailFactory.SUBMIT_NEW_EMAIL.sendUserEmail(user, submit, null);

            req.setAttribute("color","Green");
            req.setAttribute("message"," Job Successfully Submited. Sequece id : " + submit.getSeqId());
            forward("/WEB-INF/TransactionResult.jsp", req, resp); 
            return;

        }catch(Exception e){

            req.setAttribute("color","Red");
            req.setAttribute("message","Teradata failure : " + e.getMessage());
            forward("/WEB-INF/TransactionResult.jsp", req, resp);
            e.printStackTrace();
            return;

        }
     }
}

With this being the forward method I call above defined in the superclass ExtendedHttpServlet :

protected void forward(String destination, HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException 
{
    RequestDispatcher dispatcher = request.getRequestDispatcher(destination.toString());
    dispatcher.forward(request, response);
}

But with this I have to have a copy of the TransactionResult.jsp in all of my wars, and it makes maintenance a little bit of a pain.

My question is -- Is there any way I could get my forward function to find jsps in other WARs to forward to. Or maybe could I include the jsp in my EAR and have the forward find the jsp files there. It is my understanding that jsps are just files and are compiled at runtime by special servlets, so I dont see why this wouldnt be possible?

Thanks for any advice / insight / help....

Edit Since some of you asked which server, I am currently on Websphere v 7.0

gbtimmon
  • 4,238
  • 1
  • 21
  • 36

3 Answers3

2

You can obtain the other servlet context by ServletContext#getContext() and then use its request dispatcher as available by ServletContext#getRequestDispatcher(). First you need to configure the server to enable the "cross context" option. This is by default disabled on most servers. It's unclear which server you're using, so here are just some hints: for Tomcat, check the crossContext attribute of context.xml and for Glassfish, check the crossContextAllowed property of glassfish-web.xml.

Once done that, then you'll be able to obtain the other ServletContext by its context path in servlet as follows:

ServletContext otherServletContext = getServletContext().getContext("/otherContextPath");

Then, you need to obtain a RequestDispatcher from it on the path of the desired resource and invoke the forward() on it hereby passing the current HTTP servlet request and response.

otherServletContext.getRequestDispatcher("/WEB-INF/TransactionResult.jsp").forward(request, response);

A completely different alternative is to create an entirely separate Java project (called a "Web Fragment Project" in Eclipse) wherein you put the shared JSPs in /META-INF/resources folder of the Java source folder. Finally deploy all your WARs with this Java project in flavor of a JAR file in /WEB-INF/lib folder (in Eclipse, adding the standalone Java project as "Deployment Assembly" of all web projects ought to be sufficient). You can access JSPs in /META-INF/resources folder as if they are in the current WAR.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
2

If you're using a servlet 3.0 compliant server, I would recommend packaging all shared web resources (JSPs, CSS files, etc.) inside the META-INF/resources directory of a jar. Put this jar in the WEB-INF/lib of every webapp, and these shared resources will become part of the webapp, just as if they were directly in the root of the webapp.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
1

Use ServletContext.getContext() to gain access to other applications' context (within the same virtual host). After getting that you can use that request dispatcher to do the forward.

In order for the above to work, you may need to enable some vendor specific settings to override default security, see here: What does the crossContext attribute do in Tomcat? Does it enable session sharing?

Community
  • 1
  • 1
Istvan Devai
  • 3,962
  • 23
  • 21