IntelliJ provides checkbox Spring MVC project creation and easy to configure deployment to Tomcat (with one caveat).
Download and unpack Tomcat from http://tomcat.apache.org/index.html and put it wherever you keep your servers in your filesystem.
To begin select the Spring heading in the lefthand panel and check the box for Spring MVC. I’ll be using WebFlow later so I’ve checked that one too.
Go to next and name your project and click Finish and the dependencies will be downloaded to the lib directory.
IntelliJ will create the project structure including an index.jsp file in the web folder.
To deploy the project you will need to do 2 things:
- Set up a run configuration
- Add the dependencies to the build artefact
Set up the run configuration
Go to the Run menu and click Run…
and choose Edit Configurations…
In the dialog click the + sign at the top of the left hand pane and in the drop down scroll to the Tomcat entry and click the Local sub menu.
(Note: if Tomcat Server isn’t in the list, scroll to the end and click the more items…)
Choose a name for your server (I’ve called mine Tomcat) and then click the Configure button at the end of the Application server: line.
You’ll be presented with a dialog to fill out – browse to where you put your Tomcat download from earlier and select the top level directory from the download and click OK.
Once you have the application server configured, select the Deployment tab and click the + sign at the bottom of the artifact box.
In the context menu choose Artefact… and the default exploded war file should be added to the deployment list.
This should finish the Run Configuration so click Apply to store the changes and then close the dialog. It won’t deploy successfully until you’ve done the next section.
Add the dependencies to the artefact
To Run the project in Tomcat you’ll need to add in the dependencies to the artefact so open the Project Structure dialog from the menu as shown below or with the keyboard shortcut (Cmd + 😉
In the dialog, go to the Artefacts heading in the panel on the left and then find the Fix button in the bottom right hand corner. Fix each problem (there should be 2 or 3 depending on what dependencies you selected in the first screen) by adding the missing library to the artefact. Click OK when all the problems have been fixed.
Once you have fixed all the missing dependencies then you should be able to deploy the artefact directly to your Tomcat server, with the IDE starting the server on first run and then giving you the option of restarting or updating on subsequent runs.
To run go to the Run menu, click the Run… item and then choose the Tomcat run you setup earlier.
You’ll see the default index.jsp file loaded to your browser:
For subsequent runs use the button on the menu bar.
In this example I’ll create a simple Spring project in IntelliJ which will serve the current date. I’ll use multiple implementations (using the old Java Date and new DateTime classes) to demonstrate the 3 stages discussed in my last post on dependency injection.
I’ll build an interface with a
getCurrentDate() method that returns the current date and use the Spring container (which can read xml config files) to provide the implementations.
I’ll begin by creating an IntelliJ Idea Spring project called DateOutputter – check the Spring box when creating the project to add the jar files to the project’s lib folder.
And then I’ll create a package in the src directory called datetoday
Programming to an interface
As described in the previous post the first step to avoiding coupling is to program to interfaces. In this project there is only one public method required – the method that returns the current date so this should be specified by an interface. I’ll also create one of the implementations in the package so I can see the output.
Note that in the implementation I’ve provided a set method rather than instantiating the Date object in the class directly so as to be able to demo the some features of the Spring container.
Adding the container config
To add a Spring configuration file, create a file called
application.xml at the root of the
src directory. We will use this later when constructing the client to build an “application context”. A Spring class called
ClassPathXmlApplicationContext reads the file and uses the data to form the container.
Intellij will warn you that the application context is not configured for this file – click the link to correct this (i.e. to have IntelliJ recognise it as a Spring config file)
and then choose New Application Context from the drop down and click Ok on the dialog box.
Now the container is ready to use I can specify the date I want to inject into the bean. I want to inject an instance of a
java.util.Date object to the
DateTodayOldImpl class so I use the bean tag to specify the class and the property tag to identify the field. Note that although the field is called “today” the method is called setDate so the reference is to date (as derived from removing the set and converting the capital D to a lower case d).
Adding a client
Rather than use a web client, I’ll create a standalone client for demo purposes in a package called dateclient (MIGHT CHANGE THIS LATER). The client will contain a main method which will use the Spring container (which in turn will read from the appliation.xml config file) to collect an implementation of the
DateToday interface and will call its
getCurrentDate() method and print the result.
At this point I can run the client and will get today’s date output.
I have a functional date service which will run quite happily UNTIL Java’s designers finally realise how awful their Date implementation is and rewrite it based on Joda-Time. So time to update my application with the shiny new JSR 310 classes.
In my datetoday package I shall write a new implementation, update my configuration file and not do anything to my clients and from that point forward clients will use the new service without any need for updating or (on the client side) recompiling.
Now I have a new implementation I can use it just by changing the configuration file.
Note the simpler implementation here – nothing to stop me from using this with the old Date class but I wanted to demonstrate the injection process with a set method. So running this displays the date as before (well apart from format differences) with no changes on the client side.
So this post demonstrates the use of Spring to implement the 3 elements discussed to reduce coupling:
- Programming to interfaces
- Dependency injection
- Central configuration (via a container)
These come together in the client code:
The following is a brief summary of dependency injection with particular reference to architectural coupling as found in standard 3 tier Java EE type projects.
Two classes are coupled if one class contains a reference to another. In the example below the Person class is coupled to the String class as the fields of the Person class include a String type field. The Person class depends on the String class and were the behaviour of the String class to change the Person class may break.
Some coupling is a necessary part of object orientated programming but it is to be avoided as much as possible as it reduces the flexibility of your program. In the example above the dependency of the Person class on the String class is a reasonable level of coupling given the low likelihood of the String class being changed but when adding dependencies your own reference types which are much more likely to be changed in response to changing requirements then coupling becomes more of an issue. If you have a class that is coupled to a large number of other classes in your project (e.g. a Data Access Object or DAO that provides database access to throughout your project) then refactoring your project after changing the DAO is not trivial.
This problem can be ameliorated by the use of design steps collectively known as dependency injection.
- Program to interfaces – where you would usually embed your reference type into a class replace it with an Interface which specifies the behaviour your class will provide.
- Pass reference by parameters – where you have an Interface reference, initialise it by passing the implementation of the Interface as a parameter using a
setReference(InterfaceReference ir) type method.
- Centralise configuration – create a “container” that constructs the specific implementation and uses the set method defined in stage 2 to pass it the implemented interface to the dependent class
Following these 3 steps means that the interface remains constant but the implementation can be updated by changing code in the container class only. In most frameworks (e.g. Java EE, Spring) a sophisticated container is provided which can read from configuration files.