Installing Apache 2 and Tomcat 7

Overview

A tomcat instance is installed in a glimpse of an eye: after following a few steps as outlined in the tomcat documentation, it is possible to easily deploy WAR containers using the tomcat manager application. However, often this tomcat instance is configured for port 8080, and therewith not quite ready for final deployment.

While it is easy to change the port on which tomcat is hosted to the default port 80, it is not a recommended practice to manage a web server entirely using a tomcat instance. Luckily, it is relatively easy to set up an Apache web server as the ‘main’ web server and to let this server forward particular requests to a tomcat instance.

To forward particular requests from an Apache instance to a tomcat instance, a number of steps need to be performed:

  • Apache needs to be installed
  • Tomcat needs to be installed (on the same machine)
  • A ‘virtual host’ needs to be configured in Apache. Such a virtual host can be used to forward request directed to a particular domain name to an apache site. An apache site can contain static and dynamic web content in from of html files, php files or cgi script, among others. However, using a specific connector an apache ‘site’ can also point to a tomcat server.
  • On this tomcat server, it must be specified, which web applications should be served in response to the requests send by the Apache server.

In the following, all of these steps are described in some detail. In particular, it is discussed how an instance of Apache 2 can be connected to an instance of Tomcat 7. In the example given here, all applications of the tomcat server are mapped to a virtual host of an apache server (you could also configure only a single application (WAR) to be mapped to a domain of your apache server).

Installing Apache 2 in Ubuntu

Since apache is part of the Ubuntu package it can be installed using the command:

sudo apt-get install apache2

Installing Tomcat 7 in Ubuntu

At the time of this writing, Tomcat 7 cannot be installed using apt-get. Instead, the package for Tomcat 7 must be installed manually. The instructions on Diego Benna’s blog for conducting this process are excellent (also work for Ubuntu 9.10). Also, double check with Sebastian Mogilowskis’ blog post (steps 1-6).

Install Apache-Tomcat connector

In order to forward requests from Apache to Tomcat, an Apache 2 connector must be installed. This can also be achieved using aptitude:

sudo apt-get libapache2-mod-jk

Also configure the Apache wokrker and JK configuration file as shown in Sebastian Mogilowskis’ blog post (steps 7).

Setting up virtual host in Apache 2

A virtual host in Apache 2 can be set up in a number of simple steps. The created virtual host will provide access to your tomcat instance at an URL managed by your apache server.

  • Create a new directory under /var/www with the name ‘tomcat’
  • Also create the sub-directory /var/www/tomcat/logs
  • Create a file ‘tomcat’ under /etc/apache2/sites-available tomcat (for instance using sudo nano /etc/apache2/sites-available). Paste the following contents into this file (if you do not want to specify an IP address, replace XX.XX.XX.XX with *):

<virtualhost XX.XX.XX.XX>

JkMount /* default

ServerName http://www.yourserver.com

ServerAdmin servermaster@yourserver.com

DocumentRoot /usr/share/tomcat7/webapps

ErrorLog /var/www/tomcat/logs/error.log

CustomLog /var/www/tomcat/logs/access.log common

</virtualhost>

  • Replace XX.XX.XX.XX with the IP address of your server
  • Replace http://www.yourserver.com with the url you want the virtual server to persist on (you will need control of the DNS entries for this url. You will need to point them to your server IP address)
  • Enable the new site using ‘sudo a2ensite tomcat’
  • Reload the apache instance using ‘/etc/init.d/apache2 reload’ and ‘/etc/init.d/apache2 restart’

Setting up virtual host in Tomcat 7

In order for tomcat to react to the forwarded requests from the Apache server, a host needs to be configured in tomcat’s server.xml. This can be achieved through the following steps:

  • Add the following <host> element to the server.xml (eg in /usr/share/tomcat7/conf):

<Host name=”http://www.yourserver.com” appBase=”webapps” unpackWARs=”true” autoDeploy=”true”>

<Valve className=”org.apache.catalina.valves.AccessLogValve” directory=”logs”

prefix=”yourservercom_access_log.” suffix=”.txt”

pattern=”%h %l %u %t &quot;%r&quot; %s %b” resolveHosts=”false”/>

</Host>

  • Replace http://www.yourserver.com with the domain name on which your tomcat server should be hosted
  • Restart tomcat using ‘/etc/init.d/tomcat7 restart’

Conclusion

After these steps you should be able to access all the web applications registered in your tomcat servers webapps folder through the domain name you have specified.

E.g. the tomcat manager application under http://www.yourserver.com/manager

Test Environment

Ubuntu 9.10

Tomcat 7.0.12

Resources

Blog post “Install Tomcat 7 on Debian (Lenny) with virtual hosts and Apache2 integration”

Diego Benna’s Blog “Connect Tomcat 7 with Apache2 (mod_jk) and install Virtual Host”

Diego Benna’s Blog “Install Tomcat 7 on Ubuntu 10.10 and Ubuntu 10.04

Apache 2 Documentation Virtual Hosts

Large WAR file cannot be deployed in Tomcat 7

Problem

When uploading a WAR file larger than 50 MB, the Tomcat 7 Manager application reports:

The server encountered an internal error () that prevented it from fulfilling this request.

Exception java.lang.IllegalStateException:

org.apache.tomcat.util.http.fileupload.FileUploadBase$SizeLimitExceededException:

the request was rejected because its size (XXX) exceeds the configured maximum (52428800)

Solution

  • Go to the web.xml of the manager application (for instance it could be under /tomcat7/webapps/manager/WEB-INF/web.xml.
  • Increase the max-file-size and max-request-size:

<multipart-config>

<!– 50MB max –>

<max-file-size>52428800</max-file-size>

<max-request-size>52428800</max-request-size>

<file-size-threshold>0</file-size-threshold>

</multipart-config>

 

Resources

Mail List “The request was rejected because its size (102811565) exceeds the configured maximum (52428800)”

Mail List “Can’t upload large war to Tomcat 7, worked in Tomcat 6”

Handling Drag and Drop Events in Gxt TreeGrids

The Ext GWT framework offers some rather sophisticated support for drag and drop in GWT applications. However dealings with drag and drop in TreeGrids can be complicated at times, since only limited documentation apart from the examples in the showcase is provided.

Here some information, how it can be controlled, where an item can be inserted in a TreeGrid.

Element

Description

Class TreeGridDropTarget

This class can be utilized to handle drop events on a TreeGrid. It can be assigned to a TreeGrid through its constructor new TreeGridDropTarget(treeGrid).

Method showFeedback(…)

This method can be overridden in TreeGridDropTarget to achieve custom rules for where a ‘drop’ is allowed.

DNDEvent event

This is the parameter of the showFeedback method. Its attributes can be used to determine an appropriate feedback.

event.getDragSource()

Can be cast to TreeGridDragSource. Points to the source tree grid for the drop.

event.getDropTarget()

Can be cast to TreeGridDropTarget. This should point to the drop target triggering the method.

source.getData()

Can be cast to List<?>. Points to the items, which are to be dropped.

((List<?>) source.getData()).get(..)

Can be cast to TreeStoreModel. Points to a specific item, which is to be dropped.

Through the method getModel(..) of the TreeStoreModel the actual item in the drag source can be accessed (As a BaseTreeModel).

event.getTarget()

Points to a dom element where the drag is to take place. If it’s currently over a TreeNode, it can be found through:

TreeNode n = this.getTreeGrid().findNode(event.getTarget());

 

Finally, if the user feedback should be delivered, that it is illegal to drop the node at the current location, the following commands can be added to the overridden showFeedback(..) method:

Insert.get().hide();

event.getStatus().setStatus(false);

return;

If the default feedback shall be delivered, the overridden method should be called through calling super.showFeedback(event);.

Resources

Source Code of Source of TreeGridDropTarget

TreeGridDropTarget JavaDoc

DropTarget JavaDoc

Sibling Reordering DND Tree (Sencha Forum) Check here for methods to override for TreeGridDropTarget

Infinitest for Eclipse: Quick Tutorial

If there are multiple dependent projects in an eclipse workspace, it can be tedious to run the unit test of all these projects manually. Often, a failed unit test caused by a change in a different project than where the unit test is located is only discovered with a significant time gap. From there, it becomes difficult to trace back to the initial change causing the unit test to fail.

The Infinitest eclipse plug in constantly executes all relevant unit test defined in the workspace in the background. If a source file is saved, Inifitest will search for affected unit tests and execute these. If they fail, a Java problem is reported.

Below some simple steps to install and configure Inifitest:

Download

Infinitest can be downloaded using their update site: http://update.improvingworks.com

Just follow the instructions on their site to install the plugin.

Activate

Once the Infinitest plug in is installed and the eclipse IDE restated, it should start searching for test cases.

If code is changed (and saved), it should start reporting any failed test cases as Java problem.

Possible Problems

Infinitest can be disabled in the eclipse preference window. It adds a top level item “Infinitest” to the eclipse preference tree.

I encountered some problems with GWTTestCases. For every GWTTestCase in my projects, Infinitest reported:

Description    Resource    Path    Location    Type

NoClassDefFoundError (com/google/gwt/dev/cfg/Condition) in GwtTestGwtCollaborationScenario.    GwtTestGwtCollaborationScenario.java    /nxServerGwt/src/test/java/nx/servergwt/tests/hosted    line 0    Infinitest Test Failure

The only solution I found was to remove these test cases from the eclipse projects build path (right click the .java file and select Build Path / Exclude).

 

Models Driven Development and Domain Specific Languages

The question of the right programming language is one that has always spurned much controversy. Likewise, the idea that one day we could develop software by simply ‘drawing’ expressive models has as many advocators as opponents.

The idea of domain specific languages could be one which helps us to advance both of these controversies. Both programming languages and traditional models (think UML) are ultimately both just abstractions, models to use another word. More specifically, most visual modelling techniques as well as programming languages follow well-defined (more or less) grammars. In a domain specific language we utilize the power of these grammars to solve problems in one domain.

A very good introduction as well as guide to domain specific languages (DSL) has just been released by Markus Völter:

MD*/DSL Best Practices V 2.0

Below a number of citations from this document on a number of matters:

General Purpose Programming Language vs. DSL

“[T]he ability to extend existing languages (such as it is possible with MPS, Spoofax, and to some extent with Xtext2), makes it possible to build domain specific languages as extensions of general-purpose languages. So instead of generating a skeleton from the DSL and then embedding 3GL code into it, one could instead develop a language extension, that inherits for example expressions and/or statements from the general-purpose base language. This makes a lot of sense: imagine the development of a language for asynchronous, reactive programming. In this case it is very useful to be able to inherit expressions from a general-purpose base language.”

Graphical vs. Textual Notation

“Things that are described graphically are easier to comprehend than textual descriptions, right? Not really. What is most important regarding comprehensibility is the alignment of the concepts that need to be conveyed with the abstractions in the language. A well-designed textual notation can go a long way. Of course, for certain kinds of information, a graphical notation is better: relationships between entities, the timing/sequence of events or some kind of signal/data flow.”

Tooling Matters

“Defining languages and notations is not enough per se – you have to provide good tool support for them, too. […]To increase usability, DSL editors need to be able to cope with wrong or incomplete models as they are entered by the users. Ideally, it should even be possible to persist them. Of course, as long as models are wrong or incomplete they cannot be processed any further. In the context of textual languages, this might mean that you design a somewhat “looser”, more tolerant grammar, and enforce correctness via constraints.”

Critique

I personally see especially great value in building DSLs around general purpose languages, such as Java, JavaScript, Groovy, Scala, etc. Some frameworks have already gone in long way in embedding DSLs in Java Syntax. See here for instance the Mirror Project. This project aspires to make it easier to interact with the Java Reflection API. The resulting calls come close to expressions in natural language.

new Mirror().on(target).set().field(fieldName).withValue(value);

Another example is the mocking framework Mockito. This framework utilizes a DSL to specify the behaviour of ‘mocked’ objects. For instance:

when(mockedList.get(anyInt())).thenReturn(“element”);

Another premier example is the hamcrest library, which is also mainly used to support unit tests.

assertThat(theBiscuit, is(equalTo(myBiscuit)));

Further ‘DSLs’ implemented in Java based on the hamcrest library are listed in the project, which use the hamcrest library.

Many APIs are also implemented in an DSL-like fashion. For instance, the API for the NextReports framework (Dinca-panaitescu, 2011):

FileOutputStream stream = new FileOutputStream(“test.html”);

FluentReportRunner.report(report).connectTo(connection).withQueryTimeout(60).withParameterValues(createParameterValues()).formatAs(ReportRunner.HTML_FORMAT).run(stream);

Of course, there is still some way to go to improve those DSLs. Especially end users are likely to struggle with some intricacies of general programming languages. That said, I still believe that it would be easier to build powerful tools around the limitations of general purpose languages than to develop these ‘from scratch’ for other languages.

References

MD*/DSL Best Practices V 2.0 (Völter, 2011)

“Model Driven Development and Domain Specific Language Best Practices”, Jean-Jacques Dubray on Mar 28 2011 on infoq.com

Presentation “Real Software Engineering” by Glenn Vanderburg presented at Lone Star Ruby Conference 2010. (Advances that the code is the model)

“Is modelling about to overtake coding? I’m a happy SAP business consultant :)”, Thierry Crifasi on SAP Community Network posted on Dec. 13, 2010 (Advances that models should take over coding)