Having played with the java SCA examples I thought I would recreate some
HelloWorld examples as an exercise in getting a feel for how easy it is to
get up and running with Tuscany/Java without resulting to just modifying
what is already in the tuscany example directory structure.
I started with the tuscany build and samples but them created 4 of the
simplest HelloWorld configurations I could think of. This note records my
experience so far as a user new to looking at the technology. I have noted
issues as I have gone through but as the build is not yet done I expect that
some of these are just code in flight issues. So apologies for raising
things that have already been fixed.
I am happy to raise all, some, none of these are JIRA entries as appropriate
if someone can tell me which ones are bogus. Its also true that some of
these comments are subjective so feel free to ignore.
If these notes are of any use at all let me know. No doubt I will playing
more over the next week and am happy to feed back if it's useful.
Establish the environment
My OS for this exercise is Fedora Core 5. I followed the linux instructions
at http://wiki.apache.org/ws/Tuscany/GetTuscany/Linux which are pretty much
spot on. I went ahead and installed
IBM JDK 5.0 (as an alternative to the recommended Sun JDK)
Maven 2.0.4
Ant 1.6.5
There is a slight difference between Red Hat and Fedora Core
1 - There is no readily available rpm for svn on Fedora Core but Fedora
Cores come with subversion 1.3.1 in the install
2 - There are several different sets of build instructions, for example, SCA
Installation instructions, Samples setup, java/BUILDING.txt,
testing/tomcat/readme and the new wiki "Get Tuscany" pages. Personally I
prefer the latter and found the different instructions in different places
confusing
Build and test
The maven build worked straight off and the tests apparently ran. I did, and
still do, get numerous warnings that maven is unable to download
dependencies from ibiblio. It also hangs sometimes trying to get particular
jars. I let it carry on and it didn't seem to stop the test working
3 - assuming its not just me put a note in the build instructions mentioning
maven warnings that occur.
Run hello word sample
I got a little caught out here as in the snapshot I took (a few days ago!) I
have a samples directory and a samples directory under the SCA project. This
is OK but I got caught out by the two links at the bottom of the top level
sampleSetup.htm file. For some strange reason I didn't notice that one
points to the top level samples directory and the other points to the SCA
samples directory - doh. At the time there were HelloWorld samples is both
(this is not
the case now as I checked svn)
4 - May be worth putting a note in each sample readme highlighting where the
sample is in the directory structure
5 - The big bank samples overview (
file:///home/slaws/tuscany/java/samples/readme.htm) doesn't point to readmes
in the same way that the SCA samples page does (
file:///home/slaws/tuscany/java/sca/samples/readme.htm)
The jars that are required to run the samples are in the local maven
repository. The required jars are listed on the sample setup page
(file:///home/slaws/tuscany/java/sampleSetup.htm). But the list here doesn't
match the list that the build file created for me when I run with the j2se
target.
asm-2.2.jar
axis-wsdl4j-1.2.jar
common-2.2.0-SNAPSHOT.jar
commons-logging-1.0.4.jar
concurrent-1.3.4.jar
ecore-2.2.0-SNAPSHOT.jar
ecore-change-2.2.0-SNAPSHOT.jar
ecore-xmi-2.2.0-SNAPSHOT.jar
geronimo-connector-1.0.jar
geronimo-j2ee-connector_1.5_spec-1.0.jar
geronimo-jta_1.0.1B_spec-1.0.jar
geronimo-transaction-1.0.jar
sca-api-SNAPSHOT.jar
sdo-api-SNAPSHOT.jar
stax-api-1.0.jar
tuscany-common-SNAPSHOT.jar
tuscany-container-java-SNAPSHOT.jar
tuscany-core-SNAPSHOT.jar
tuscany-databinding-sdo-SNAPSHOT.jar
tuscany-model-SNAPSHOT.jar
tuscany-sdo-impl-SNAPSHOT.jar
wstx-asl-2.8.2.jar
xsd-2.2.0-SNAPSHOT.jar
6 - check that the jar lists on the sample setup page (
file:///home/slaws/tuscany/java/sampleSetup.htm) are correct.
The build script to copy these jars to a useful place is hidden away in
testing/tomcat. This is a really handy script but its got quite a lot of
targets and is quite dense.
7 - consider making a wrapper for the build.xml file to expose some some of
the often used targets without all the other stuff, for example, I made the
following in the tuscany/java directory.
<project name="useful targets " default="prepareForHelloWorld" basedir='.'>
<target name="prepareForHelloWorld" >
<ant antfile="testing/tomcat/build.xml" target="j2se">
<property name="tuscany.acceptance.target.dir" value="target"/>
</ant>
</target>
<target name="runHelloWorld">
<java classname="
org.apache.tuscany.samples.helloworldmc.HelloWorldClient"
fork="true">
<jvmarg value="-Djava.ext.dirs=./target/j2se"/>
<classpath>
<pathelement
location="samples/helloworld/helloworldmc/target/helloworldmc-SNAPSHOT.jar
"/>
</classpath>
</java>
</target>
</project>
8 - When setting up for tomcat there is a suggestion that the build file is
edited to set the local tomcat location. A target could be created to prompt
for this input in the first instance, something like..
<target name="fixUpTomcat" >
<input message="Please tell me where you insalled tomcat 5.5.16+ (please
enter the full path to the tomcat install directory, e.g
/home/simon/tuscany/apache-tomcat-5.5.16)" addproperty="tomcatdir"
defaultvalue="apache-tomcat-5.5.16">
</input>
<condition property="tomcatDirValid">
<available file="${tomcatdir}/conf/server.xml"/>
</condition>
<fail unless="tomcatDirValid">Invalid tomcat dir provided</fail>
<ant antfile="testing/tomcat/build.xml" target="tuscany.tomcat.fixup"
inheritall="false">
<property name="tuscany.acceptance.tc.dir" value="${tomcatdir}"/>
</ant>
</target>
After following the various setup steps I successfully ran the HelloWorld
sample. I also tried the BigBank sample but kept getting a null
pointer error. I note from the mail list however that I am not alone in this
so I will wait for the proper build before trying BigBank again.
9 - I did try to run the HelloWorldJSON-RPC sample and it failed looking for
the sca.js file which didn't appear to be in my snapshot. However I note
this
sample has now gone so we can probably ignore this.
With the setup complete I moved on to recreating the HelloWorld type samples
but outside of the tuscany directory structure. I decided on 4 easy tests in
the first instance in order to start becoming familiar with SCA components
and how they are configured.
helloworld1 - single component not using annotations
helloworld2 - single component using side file
helloworld3 - single component using annotations
helloworld4 - multiple components using annotations
helloworld1
The intention here is to take the simplest path possible in order to get a
component up and running. The component in question simply returns a string
form a local property when the getResponse() method is called
While the Tuscany project itself uses the Maven system as a build
environment to add much needed consistency and automation to the build
process I chose to step outside of this and do the building manually. Just
to see what happens.
Having said this the first thing I did was set up a directory structure that
mirrors the maven structure so that I could be reasonably sure I was putting
things in the correct place.
hellworld1
src
main
java - where the java source files go
org
sample
helloworld
HelloWorldServiceImpl.java
HelloWorldClient.java
resource - where data and configuration files go
sca.module
test
java - where the files used to test the above source files go
target
classes - where the compile class files will go
Where
HelloWorldServiceImpl.java =
package org.sample.helloworld;
import org.osoa.sca.annotations.Service;
import org.osoa.sca.annotations.Property;
/**
* This class implements the HelloWorld service component.
*/
public class HelloWorldServiceImpl {
public String response;
public String getResponse() {
return response;
}
}
HelloWorldClient.java = pretty much the same as the clients provided with
Tuscany. I.e. I copied it.
sca.module =
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.osoa.org/xmlns/sca/0.9"
xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
name="HelloWorld">
<component name="HelloWorldServiceComponent">
<implementation.java
class="org.sample.helloworld.HelloWorldServiceImpl"/>
<properties>
<v:response>Hello</v:response>
</properties>
</component>
</module>
The real hard thing about this was realising that I need so few files. It
took a while to work out that I needed neither annotations or side files for
this
very simple test. In fact I was a little surprised that it worked but there
you go.
The other thing that confused me was the use of the work client. The test
client that appears in the samples and tests is a local client that uses
TuscanyRuntime API to get going. This is slightly different from client in
spec terms and this differs again from a remote client that just happens to
be
calling the module via, say, web services. I guess the test client is sort
of like a client with a local java binding (sort of but not quite). Not sure
what
to do about this though. Needs to go in the primer.
I compiled with...
javac -classpath target/classes:\
../tuscany/java/target/j2se/sca-api-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-core-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-common-SNAPSHOT.jar:\
. -d target/classes src/main/java/org/sample/helloworld/*.java
I'm assuming that the directory paths for the M1 jars will change when the
release is done but for now I'm using the Jars that are recommended for J2SE
development.
I ran with
java -classpath target/classes:\
src/main/resources:\
../tuscany/java/target/j2se/sdo-api-SNAPSHOT.jar:\
../tuscany/java/target/j2se/sca-api-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-core-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-common-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-model-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-sdo-impl-SNAPSHOT.jar:\
../tuscany/java/target/j2se/axis-wsdl4j-1.2.jar:\
../tuscany/java/target/j2se/ecore-2.2.0-SNAPSHOT.jar:\
../tuscany/java/target/j2se/common-2.2.0-SNAPSHOT.jar:\
../tuscany/java/target/j2se/ecore-change-2.2.0-SNAPSHOT.jar:\
../tuscany/java/target/j2se/stax-api-1.0.jar:\
../tuscany/java/target/j2se/wstx-asl-2.8.2.jar:\
../tuscany/java/target/j2se/geronimo-connector-1.0.jar:\
../tuscany/java/target/j2se/geronimo-j2ee-connector_1.5_spec-1.0.jar:\
../tuscany/java/target/j2se/geronimo-transaction-1.0.jar:\
../tuscany/java/target/j2se/geronimo-jta_1.0.1B_spec-1.0.jar:\
../tuscany/java/target/j2se/concurrent-1.3.4.jar:\
../tuscany/java/target/j2se/commons-logging-1.0.4.jar:\
../tuscany/java/target/j2se/xsd-2.2.0-SNAPSHOT.jar:\
../tuscany/java/target/j2se/tuscany-container-java-SNAPSHOT.jar:\
. org.sample.helloworld.HelloWorldClient
10 - The message you get when the runtime can't find the sca.module file is
not great.
Exception in thread "main"
org.apache.tuscany.core.config.ConfigurationLoadException: sca.module
at
org.apache.tuscany.core.config.impl.AbstractModuleComponentConfigurationLoader.loadModuleComponent
(AbstractModuleComponentConfigurationLoader.java:116)
at
org.apache.tuscany.core.config.impl.AbstractModuleComponentConfigurationLoader.loadModuleComponent
(AbstractModuleComponentConfigurationLoader.java:100)
at
org.apache.tuscany.core.client.TuscanyRuntime.<init>(TuscanyRuntime.java
:102)
at
org.apache.tuscany.core.client.TuscanyRuntime.<init>(TuscanyRuntime.java:67)
at
org.sample.helloworld.HelloWorldClient.main(HelloWorldClient.java:17)
After a bit of fiddling with the classpath and it worked.
helloworld2
Having done the most stripped down example I could I wanted to explore how
components are defined a little. I had the option of looking at annotations
or side files and, for some reason, choose to look at side files. This may
have been a mistake as a spent quite a bit of time on this and couldn't get
it to
work
hellworld2
src
main
java - where the java source files go
org
sample
helloworld
HelloWorldService.java
HelloWorldServiceImpl.java
HelloWorldClient.java
resource - where data and configuration files go
org
sample
helloworld
HelloWorldServiceImpl.componentType
sca.module
test
java - where the files used to test the above source files go
target
classes - where the compile class files will go
HelloWorldService.java =
public interface HelloWorldService{
public String getResponse();
}
HelloWorldServiceImpl.componentType =
<?xml version="1.0" encoding="ASCII"?>
<componentType xmlns="http://www.osoa.org/xmlns/sca/0.9"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<service name="HelloWorldService">
<interface.java interface="org.sample.helloworld.HelloWorldService
"/>
</service>
<property name="response" type="xsd:string" default="HelloDefault"/>
</componentType>
I added this interface and specialized it as I was having problems and the
side file references an interface.java element. It didn't make any
difference.
I was expecting the default value to be returned when I called getResponse()
on HelloWorldServiceImpl but fo some reason it doesn't want to play.
11 - there is a lack of java examples that use side files - are side files
important?
12 - I turned logging on to try and work out if the sidefile was being
loaded. I thought I might have in in the wrong place. It was being loaded
but the logging output is not all that useful
May 9, 2006 2:36:24 AM
org.apache.tuscany.core.loader.impl.StAXLoaderRegistryImpl$Monitor
registeringLoader
FINEST: Registering StAXElementLoader for
{http://www.osoa.org/xmlns/sca/0.9}entryPoint
May 9, 2006 2:36:24 AM
org.apache.tuscany.core.loader.impl.StAXLoaderRegistryImpl$Monitor
registeringLoader
etc.
It tells you things are happening but doesn't give you this instance
information.
I followed the code to find where side files are loaded.
13 - There are very few comments in the code
Ultimately I noticed JIRA 321 which points out a side file issue with
references. It doesn't say that the example I have won't work but maybe I
caught the code in flight.
helloworld3
I now switched to annotations. Which, for my very simple example, worked
fine first time.
helloworld3
src
main
java - where the java source files go
org
sample
helloworld
HelloWorldService.java
HelloWorldServiceImpl.java
HelloWorldClient.java
resource - where data and configuration files go
sca.module
test
java - where the files used to test the above source files go
target
classes - where the compile class files will go
In this case
HelloWorldServiceImpl.java =
@Service (HelloWorldService.class)
public class HelloWorldServiceImpl implements HelloWorldService {
@Property
public String response;
public String getResponse() {
return response;
}
}
helloworld4
The next step was to do a little aggregation
helloworld4
src
main
java - where the java source files go
org
sample
helloworld
HelloWorldService.java
HelloWorldServiceImpl.java
HelloWorldServiceAggregatorImpl.java
HelloWorldClient.java
resource - where data and configuration files go
sca.module
test
java - where the files used to test the above source files go
target
classes - where the compile class files will go
In this case
HelloWorldServiceAggregatorImpl.java =
@Service (HelloWorldService.class)
public class HelloWorldServiceAggregatorImpl implements HelloWorldService {
@Reference
public HelloWorldService serviceA;
@Reference
public HelloWorldService serviceB;
public String getResponse() {
return serviceA.getResponse() + serviceB.getResponse();
}
}
and
sca.module =
<?xml version="1.0" encoding="UTF-8"?>
<module xmlns="http://www.osoa.org/xmlns/sca/0.9"
xmlns:v="http://www.osoa.org/xmlns/sca/values/0.9"
name="Helloworld">
<component name="HelloWorldServiceAComponent">
<implementation.java
class="org.sample.helloworld.HelloWorldServiceImpl"/>
<properties>
<v:response>Hello</v:response>
</properties>
</component>
<component name="HelloWorldServiceBComponent">
<implementation.java
class="org.sample.helloworld.HelloWorldServiceImpl"/>
<properties>
<v:response>World</v:response>
</properties>
</component>
<component name="HelloWorldServiceAggregatorComponent">
<implementation.java
class="org.sample.helloworld.HelloWorldServiceAggregatorImpl"/>
<references>
<v:serviceA>HelloWorldServiceAComponent</v:serviceA>
<v:serviceB>HelloWorldServiceBComponent</v:serviceB>
</references>
</component>
</module>
This worked fine and by this stage I was starting to build up a little
confidence and can see a
way forward to trying lots more interesting combinations
Regards
Simon