Creating a standalone Spring application
8/9/2016 (updated)
Anthony Toyofuku
Contents
Introduction
Creating a project in Eclipse using a Maven archetype
Adding Spring to the project
Wiring up Spring
Adding encrypted passwords using Jasypt
Jasypt and Maven
Introduction
The goal is to create a Java application, runnable from the command line (CLI) that connects to a RESTful web service spitting out JSON or XML and outputs the results to a variety of file formats: comma separated values (CSV), Excel, or the raw data. This tutorial will touch on the basics of how to do this using the Spring Framework.
Much has been written about Spring and how to create an application using the framework. Many of the tutorials focus on creating an MVC web application for deployment inside a servlet container such as Tomcat. Nowadays it seems like there is a lot of work around Spring Boot for quickly creating web applications.
As the focus of this tutorial is on creating a program that is invoked from the command-line, as opposed to a web app, it seems that Spring Boot would be overkill. So in the interest of relative simplicity coupled with the facts that I've never written anything using Spring Boot, and I'm wary of any software that prides itself on being "opinionated", this tutorial will use plain, long-in-the-tooth Spring.
The source code for this project is available at: https://github.oit.uci.edu/esb/masala
Creating a project in Eclipse using a Maven archetype
What immediately follows are screenshots of how to create a simple application, using Maven from within Eclipse. It assumes that you have Eclipse installed. If you prefer to work from the command line, instructions are available here.
In the filter text box, type "maven-archetype-quickstart", that archetype should appear in the Artifact Id. Select it and press the "Next" button.
In the "New maven project" dialog, for this test project, I entered in "edu.uci.oit.middleware" for the Group Id and "masala" for the Artifact Id. You will want to enter in whatever values suit your needs. Then press the "Finish" button.
With that done, we have a fully functioning application. You can build the project from within Eclipse by clicking on the "Project" tab, and then "Clean…". On the dialog that shows up next, you can click "OK".
You can now execute the program from within Eclipse by pressing the "Run" icon. If you are successful, you should see "Hello World!" in Eclipse's console window.
Adding Spring to the project
Now that we have created the barebones project, we're ready to add in the Spring libraries to the pom.xml. In Eclipse, navigate to the pom.xml file, and open it by double clicking on it:
Once the pom.xml is open, I prefer to edit the file directly as a text file, rather than using pom editor. To view the raw file, click on the "pom.xml" tab:
We're to add two dependencies, one for the spring-core, and second for spring-context. I decided to go with the most recent version of Spring, which as of this writing is 4.3.2.RELEASE. To see the most recent version, I went to https://mvnrepository.com/tags/spring. After clicking around, as of today the most recent version for the 4 branch is 4.3.2.RELEASE. Clicking on those links gives me the actual Maven dependency block, which I cut and paste into the pom.xml file. Notice that I turned the Spring version into a property "spring.version" and replaced the hard coded reference to version in both spring-core and spring-context to be the property ${spring.version}. Note: the screenshot below lists the version as 3.2.17.RELEASE. I changed it to use the 4 branch.
For the moment, that will do it for the Spring libraries. We can now save and close the pom.xml file.
Wiring up Spring
Now it's time to create the directory where the spring-context.xml file will reside, and then create an empty spring-context file.
In the next dialog, create a folder named "src/main/resources/spring"
After you press the "Finish" button, the directory will appear in the left Package Explorer pane. You will now want to create the file "spring-context.xml" in the newly created directory. The actual name "spring-context.xml" is arbitrary. As long as it ends in "xml", you can name it as you see fit.
For the moment, I'm only going to put only the XML namespace declaration in it. We'll fill in more a bit later:
Adding an interface and concrete classes
In the interest of time, we're now going to do several things, some of which might not have accompanying screenshots.
Create a Java interface:
Create a two classes that implement Salutation interface.
After the interface and the two concrete classes, it will look like this (I've created three source code panes just for ease of viewing)
We are now going to change the main class, currently still named "App.java" and add some code so that it's wired up to Spring:
Now we need to edit the spring-context.xml file to wire the concrete implementation of a Salutation. We'll stick with the saying "Hello" for the moment.
You should now be able to run the program by hitting the green ">" button in Eclipse (you might need to do "Project | Clean | … " first). And it should say "Hello world".
Experiment with replacing the HelloSalutation bean with the GoodbyeSalutation bean by changing the entry in the spring-context.xml file.
Adding a properties file
Spring makes it easy to read from properties files. In your bean file (spring-context.xml in this case), I added the following bean invocation:
When the application is fired up, it will look for a file named "masala.properties" located somewhere on the classpath. I put the file in the src/main/resources directory:
Which for the moment contains one name/value pair:
While I'm at it, I also create a new implementation of the Salutation interface that uses a setter to set the value of the sentence via runtime configuration:
We can now configure the spring-context.xml file to read from the properties file to inject a sentence at run-time:
Making the project executable from the command line
Up to this point, we've been testing and running the project through Eclipse. In this section we will add Maven plugins that will create a jar file that is executable from the command line as:
% java –jar target/masala.jar
Note: I have renamed the file App.java to Main.java
For ease of deployment, I'm using the "uber" jar "maven-shade-plugin" which packages everything into one giant, "uber" jar. If you prefer to have the application jar separate from the library dependencies, you can use a combination of the maven-dependency-plugin and the maven-jar-plugin.
To use shade, merely add the following block into your pom.xml file, in the build/plugins section
After adding that block, once you package the project using Maven package, you should then be able to drop down to a command line prompt and type java –jar target/masala.jar and you should get your desired output. The example below intersperses the log4j output with the line "Hello from the properties file, via Spring configuration."
Adding encrypted passwords using Jasypt
With Spring, it's relatively straightforward to use the Jasypt encryption libraries. The first step before we start is to download the Jasypt libraries and binaries so that we can encrypt a password. The download page is: http://www.jasypt.org/download.html. I'll download the latest zip file, store it somewhere convenient, and unzip it. A whole slew of files are unzipped. Note on my Windows machine here at work, I must put the zip in my C:\OITDevEnv, otherwise I don't have the permissions to execute the batch file, getting the error "This program is blocked by group policy."
Change into the jasypt bin directory, ie:
% cd jasypt-1.9.2/bin
Jasypt uses the concept of a "master password" that you use as a seed to encrypt your database passwords, etc. This master password MUST be known when for both encryption and decryption. For our example, I'll use the master password of "mysecret". Assume for the purpose of this example that the password I want to encrypt is "login_password". Here's how I encrypt that string using Jasypt's encrypt.bat file:
% encrypt.bat password=mysecret input=login_password
Notice that somewhat confusingly, in Jasypt's case "password" refers to the master password, not the actual password that you want to encrypt. Here is the sequence, cut-and-pasted from my Cygwin windows:
In this example, the string under OUTPUT is the encrypted password. We can verify this by running the decrypt script. Notice in this case, we swap the input for the encrypted string from above:
From here on out, we will use the encrypted string in the properties file, bracketed by ENC(), ie ENC(0eQxzPgvBEfUC60jKvq5dgeMvik8RGFE).
To demonstrate using Jasypt, I'm going to write a Junit test. On the github repository, I've created a new test "JasyptTest.java", along with the corresponding "test-context.xml" and "test.properties" files. The Spring context file, "test-context.xml" contains the following:
The properties file, "test.properties" contains the following entries:
Notice that the password is Jasypt encrypted, using the encrypted version of "login_password" that we encrypted above. The password is surrounded by the Jasypt key "ENC(…)", which signals to the Jasypt property placeholder configurer to decrypt the password.
Finally, the Java code for the jasypt junit test looks like this:
Jasypt and Maven
We're now going to switch gears and add the necessary libraries to the pom.xml file, and adding the configuration to the spring-context.xml file. The necessary Maven dependencies are specified here: http://www.jasypt.org/maven.html. We are using Spring 4, so we should use the jasypt-spring31 artifact. In the properties section, we have <jasypt.version>1.9.2</jasypt.version>, then in the dependencies, the following are added:
For the moment, that's all.