Youssef Youssef - 1 month ago 14
Apache Configuration Question

Separate project in two part with Apache tomcat

I have two part in my application : administration and client part.


  • In administration the admins upload files and fill a form and make some others administration tools.

  • In client side the users make a search over entities saved from administration part.



I run this in the same project with tomcat server but sometimes when uploading files i got
Java Heap
problem and the server get down and the users can't make search anymore until i restart the server and also i don't want charge the bandwidth with uploading files. And there is conflict between session variables and timeout.

So I want separate them into two independent projects


  1. How to run two projects so if the admin project is down my clients continues to use my web app ?

  2. And How can i call commons services (controllers) and commons resources (img, files, css, js, ...) between client & admin part ?


Answer

Your question is very broad, so it's almost impossible to answer.

Heap issues

First, the reason for heap issue might as well be that you're buffering the entire uploaded file in memory (i.e. you deserialize the uploaded image into byte[] or anything like that). This is something you never do with untrusted content or reasonable size limits, as someone might upload a 16GB file and destroy your RAM completely. Instead, you can stream the uploaded bytes either to disk or to something else that works with streams.

FileUpload from Apache Commons gives you a nice and simple way to take uploads of arbitrary size and dynamically decide whether to buffer them in memory or disk based on size:

// Create a factory for disk-based file items
DiskFileItemFactory factory = new DiskFileItemFactory();

// Set factory constraints
factory.setSizeThreshold(yourMaxMemorySize);
factory.setRepository(yourTempDirectory);

// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);

// Set overall request size constraint
upload.setSizeMax(yourMaxRequestSize);

// Parse the request
List<FileItem> items = upload.parseRequest(request);

Separating the apps

On the topic of separating applications, just make 2 WARs, no magic there. But keep in mind that whatever crashes your app due to heap problems, is likely to crash the entire JVM, so to isolate them, you'll need to deloy them into separate JVMs (i.e. separate Tomcat instances).

To share common classes, like controllers, just separate them into a JAR that both WARs depend on. A simple maven multi-module project will do, one module for each WAR, and one for each shared JAR.

The resources you can share in a few ways:

  • Also package them into a shared JAR under META-INF/resources: This is supported starting from Servlet 3.0. Here's a detailed guide. This approach has the benefit of being simple to deploy, just treat the resources JAR as any other dependency. The down side is that it doesn't allow for easy redeployment without restarting the app.
  • Deploy them to a shared drive: You have to manage a separate deployment, but you can always redeploy without affecting the app.

Shared JAR with static resources

If in your classpath (meaning inside WEB-INF/lib/ of your WAR) you have a JAR that contains META-INF/resources/image.jpg, you'll be able to access it via:

http://localhost:8080/<subcontext>/image.jpg

See the guide for more details.

Shared external location

You can tell Tomcat to look for resources in an external location. The configuration is different for different Tomcat version:

  • Using aliases
<Context aliases="/images=/var/www/images" />
  • The same configuration using Tomcat 8's Resources.
<Context>
  <Resources>
    <PostResources className="org.apache.catalina.webresources.DirResourceSet"
                   base="/var/www/images" webAppMount="/images" />
  </Resources>
</Context>

You then put static resources into /var/www/images (e.g. /var/www/images/image.jpg) and access them via http://localhost:8080/<subcontext>/images (e.g. http://localhost:8080/<subcontext>/images/image.jpg).

See this tutorial for more examples.