Moving on to Seasar by H.Ozawa
In our earlier examples, we've seen how using interfaces can make the "Hello World" program flexible. In this page, we'll see how using Seasar can make the program more maintainable.
We'll be using the same Greeting.java, GreetingClient.java, and GreetingClientImpl.java as in Why Use Interfaces? page.
We'll just change GreetingImpl.java to output "3 Hello World" this time.
(GreetingImpl.java)
public class GreetingImpl implements Greeting {
public String greet() {
return "3 Hello World!"; // output message
}
}
Seasar is a DI container with AOP. What this means is that we can define variables types in an external configuration file. This external configuration file is most often a xml like the Greeting.dicon file below. It is a convention to use file extension "dicon" for Seasar extension file. Abiding by convention make our program more manageable as we'll see later on.
Line <component name="greeting" class="examples3.GreetingImpl"> tells Seasar that variable "greeting" is of class "examples3.GreetingImpl". In the same manner, line <component name="greetingClient" class="examples3.GreetingClientImpl"> tells Seasar "greetingClient" is of class "examples3.GreetingClientImpl".
Line <property name="greeting">greeting</property> tells "greetingClient" has a property "greeting".
(Greeting.dicon)
What the application program now have to do is to read in the configuration file , get an instance of an implementation of an interface, and invoke a method in the instance. In this example, configuration file is "Greeting.dicon", the interface we want to use is "GreetingClient", an implementation of this interface is "GreetingClientImpl", an instance of this implementation is "greetingClient" (as we defined in the configuration file), and the method to invoke in this interface is "execute()".
(HelloWorld3.java)
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.S2ContainerFactory;
import org.seasar.framework.util.ResourceNotFoundRuntimeException;
public class HelloWorld3 {
// relative path of the configuration file
private static final String CONFIGURE_PATH = "Greeting.dicon";
public static void main(String[] args) {
try {
// create an Seasar container using the configuration file
S2Container container = S2ContainerFactory.create(CONFIGURE_PATH);
// get instance of "greetingClient" from the container
GreetingClient greetingClient
= (GreetingClient) container.getComponent("greetingClient");
greetingClient.execute(); // output the message
} catch (ResourceNotFoundRuntimeException e){
System.out.println("Configuration file \"" + CONFIGURE_PATH + "\" not found.");
}
}
}
Execution result:
To run the example, first open the examples3.bat with a text editor and set the path of S_LIB to the lib folder of seasar2.
Remember, to use Seasar, following jar files are required in the classpath.
Additionally, following properties file is also required.
log4j.properties
We could add these jar files in the operating system environmental variable or specify them when invoking javac and java.
(examples3.bat)
@echo off
REM change the path below to where Seasar2 was extracted
SET S_LIB=C:\seasar2\lib
SET SCLASSPATH=%S_LIB%\javassist.jar;%S_LIB%\commons-logging.jar;
%S_LIB%\log4j-1.2.8.jar;%S_LIB%\ognl-2.6.5.jar;%S_LIB%\aopalliance.jar;
%S_LIB%\servlet-api.jar;%S_LIB%\s2-framework-2.3.0.jar;%S_LIB%\log4j.properties
javac -cp .;%CLASSPATH%;%SCLASSPATH% -d examples3 examples3\*.java
cd examples3
java -cp .;%CLASSPATH%;%SCLASSPATH% examples3.HelloWorld3
cd ..
Execute the "examples3.bat" file that is included with the source code. Trace with the message "3 Hello World!" is outputted to the console.
Now, we only have to change the configuration file to change the implementation. That is, we won't have to recompile the Java codes! Let's change the implementation of Greeting to Greeting2Impl.
(Greeting.dicon)
Execution result after the change:
To run the example, execute the "examples3.bat" file that is included with the source code. Trace with the message "3b Hello World!" is outputted to the console.
In this example, we'll apply an aspect to output a trace the process. Only the Greeting.dicon file needs to be modified. All other files are the same as the last example above.
Lines to trace is in maroon. Line <include path="aop.dicon"/> reads in aop.traceInterceptor that will output the trace. Line <aspect>aop.traceInterceptor</aspect> applies the aop.traceInterceptor to the component (variable) it is included in.
(Greeting.dicon)
Execution result:
To run the example, we need to add file aop.dicon file which we specified in the Greeting.dicon file. In the source code file available above, it's in the root folder.
Execute the "examples4.bat" file that is included with the source code.
This seems to be convenient but in the production application system, there are many classes. This means we'll have to write and write xml configuration files. This is not fun. This is where convention comes in. If we stick to a convention, we could just tell Seasar to define all instances of all Java classes in a folder with a specific file name.
First, we'll create folders "dicon", "impl", and "main" for dicon files, implementation files, and applications files respectively and move the respective files into the folders as below:
All except the Greeting.dicon is the same as the above example.
Configuration Greeting.dicon is changed as below to make Seasar automatically associate variables with object types.
Lines <component class="org.seasar.framework.container.autoregister.FileSystemComponentAutoRegister"> and <component class="org.seasar.framework.container.autoregister.AspectAutoRegister"> tells to associate classes and aspects respectively.
Line <initMethod name="addClassPattern"> is used to specify which files to use to generate associations.
Lines <arg>"examples4.impl"</arg> and <arg>".*Impl"</arg> tells to use all files with file name ending with "Impl" in folder "examples4.impl".
Line <initMethod name="registAll"/> tells to
actually tell Seasar to generate associations for these files.
Aspect is specified in the same manner as the example above.
(Greeting.dicon)
There isn't a major change in HelloWorld program except a try { - } finally { block was inserted to explictly clean up the container. When using automatic generation, line container.destroy(); is necessary in the try - finally block so the .destroy() method will be executed even when there is an exception.
(HelloWorld5.java)
Execution result:
To run the example, first open the examples5.bat with a text editor and set the path of S_LIB to the lib folder of seasar2.
(examples5.bat)
@echo off
REM change the path below to where Seasar2 was extracted
SET S_LIB=C:\seasar2\lib
SET SCLASSPATH=%S_LIB%\javassist.jar;%S_LIB%\commons-logging.jar;
%S_LIB%\log4j-1.2.8.jar;%S_LIB%\ognl-2.6.5.jar;%S_LIB%\aopalliance.jar;
%S_LIB%\servlet-api.jar;%S_LIB%\s2-framework-2.3.0.jar;%S_LIB%\log4j.properties
javac -cp .;%CLASSPATH%;%SCLASSPATH% -d examples5 examples5\*.java
javac -cp .;%CLASSPATH%;%SCLASSPATH% -d examples5 examples5\main\*.java
javac -cp .;%CLASSPATH%;%SCLASSPATH% -d examples5 examples5\impl\*.java
cd examples5
java -cp .;dicon;%CLASSPATH%;%SCLASSPATH% examples5.main.HelloWorld5
cd ..
Execute the "examples5.bat" file that is included with the source code.
Seasar has more features to make application system development easier. Additionally, Seasar has many family software like S2Struts and S2Hibernate to enable us to use many deFacto software.