In Java data can be transferred between programs, from files to programs or from networks to programs using I/O streams. Streams can be written to or read from by programs. Streams can be pipes for data but can optionally transform their data. Streams can contain bytes, other primatives, localized characters or serialized objects.
The most basic stream types are byte streams, which inherit from the abstract classes
OutputStream. InputStream is the parent to a large number of byte stream classes as shown in the list of direct subclasses below:
Reading data from a
FileInputStream is straight-forward with the only complications being that exceptions are throw by the file handling process. The simplest program to read from a file is shown below – this will print the int values of the characters not the characters themselves. Note that the stream is not closed, potentially a resource leak so handle this with a finally block in production code or try with resources as below.
And a version with improved exception handling (although not logging for simplicity). There is no explicit call to close the stream here as the try with resources construct will auto close the stream on exiting the try block (hence the declaration of the IOException).
Aside: The try with resources will suppress the close() exception and throw the read() exception if errors occur on both unlike in a finally block where the close() exception will suppress the read() exception.
So far, so working but this would be an unusual use of I/O streams. The stream contains character data but the
read() method returns int values. The values could be cast to characters (assuming the file contains characters with no code points above 127 – see Joel’s old article for a reminder about Unicode which is untested in this program).
char c = (char) i;
Aside: that the LANG env property will give you the default encoding behaviour for files created by vim unless overriden by a setting in .vimrc or the use of :set fileencoding
The preferred method would be to use a stream that accounts for the character data. Character stream classes inherit from the abstract classes
Writer, and again have a number of concrete subclasses, for example
FileReader as used in the example below. In this code the stream’s read method returns int values that are based on the 2 byte char primitive rather than byte values. The constructor assumes the default encoding of the platform (in my case UTF-8). Note that the cast is still present but it will handle code points over 127 correctly for default encoded files.
If a file is supplied in a different encoding then the correct strategy will be to construct an
FileInputStream which is a byte stream specialized for reading from the file system and wrap it in an
InputStreamReader which converts the bytes provided by the FileInputStream to chars using the encoding specified in the constructor.
Note the use of the semi-colon separator in the resource set up – generally prefer this to anonymous construction for localisation of exceptions. Not much in it in this case as they throw different exceptions that have different handlers but may not always be the case.
Both byte and character streams have a method called
read() that acquires a small part of the stream at a time, usually delegated to the underlying O/S. If the aquisition of bytes or characters involves a network or disk access then this method of operation will be inefficient.
A buffered I/O stream resolves this problem by running a continuous set of read operations to fill a local area of memory (a byte array) called the buffer. Once the buffer is full then it is read to emptyness and then refilled in another continious set of I/O operations.
The wrapping idiom in the code above, where a byte stream (
FileInputStream) was wrapped by a character encoding stream
(InputStreamReader) is used to achieve buffering. Buffered streams are used to wrap byte or character streams.
Note the use of the
readLine() method rather than the
read() method. This will read “\r\n”, “\r” or “\n” as a line terminator.
The Scanner API
The stream readers above can read characters, bytes and lines but to customise tokenisation (i.e. to read words (whitespace separated) or any other regex as a separator then Java provides a class called Scanner. Scanner has constructors that take
Stream objects and methods that allow the reading of all primitives other than
char and user defined tokens as
String objects as well as
Note that the
IOException on the underlying stream is handled by the Scanner’s
close() method which must be called hence the try with resources. Scanners are reasonably adept at reading numbers in different formats – see the Oracle I/O trail for an example.
Coding in the original Hibernate style using SessionFactory and Session with a static utility method to set up the SessionFactory depends on Hibernate core but using JPA with Hibernate as the datasource provider has an additional dependency on the Hibernate entity manager package. Specifying JPA with Hibernate as provider does NOT add this package to your lib folder – you will need to go and get it from maven central (and add it to any build artefacts).
If your using a Maven project then the dependencies are:
Once you have added the required dependencies then create the directory META-INF in /main/java/resources and create the file persistence.xml in that directory.
I’m using derby for the example but swap the dependency above for the driver for your database of choice. The persistence.xml file holds the details of the connection used by the entity manager and is referenced by the name of the persistence unit (DbConf in the example below).
Not the use of “create” as the value for hbm2ddl – this create the database tables on each run. Alternative settings include validate and update.
It’s also worth setting up some logging. I’ve added log4j (not log4j 2) into the dependencies and to configure the logging add a log4j.properties file to the resources folder. In the example below I’ve left the logging to trace.
Using the ORM is then a simple matter of creating an entity manager from the persistence.xml properties and specifying the domain class using the appropriate annotations.
My domain class meets the minimum requirements for a persistent class. It is annotated with @Entity, has a field specified as @Id and has a no arg constructor.
At this point running the main method should insert a table and record into a derby database (assuming derby is running – download and set up from https://db.apache.org/derby/)
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.