Create the Web service: the Java classes
Now that you have all the support files in place, it's time to start creating the Java classes necessary to run the actual service.
First, you should take care of a little housekeeping. Use Ant to compile the service and copy all of the necessary JAR files from the Muse installation to the Web application's lib directory. But ultimately, you need to set your CLASSPATH, so you might as well do it now. Set the CLASSPATH as shown in Listing 5.
Listing 5. Setting the CLASSPATH
set
CLASSPATH=%CLASSPATH%;<MUSE_HOME>\modules\core\muse-core-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\core\muse-util-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\core\muse-util-xml-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\core\muse-util-xstream-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\core\muse-wsa-soap-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\ws-fx-api\muse-wsrf-api-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\modules\ws-fx-impl\muse-wsrf-impl-2.1.0-
SNAPSHOT.jar;<MUSE_HOME>\lib\axis2\WEB-INF\lib\xercesImpl-
2.8.1.jar;<MUSE_HOME>\lib\common\xstream-1.1.2.jar;
|
Now you can create the actual classes.
Create the interface: DerbyControl.java
You can start by creating the interface that defines your actions. Create the directory <APPHOME>\src\org\apache\muse\test\derby\, and add a new file called DerbyControl.java. Add the code shown in Listing 6.
Listing 6. The DerbyControl.java
package org.apache.muse.test.derby;
import org.apache.muse.ws.resource.WsResourceCapability;
import org.apache.muse.ws.resource.basefaults.BaseFault;
public interface DerbyControl extends WsResourceCapability {
String NAMESPACE_URI = "http://ws.apache.org/muse/test/derby-control";
String PREFIX = "http";
void start() throws StartFailedFault;
void stop() throws StopFailedFault;
}
|
This simple interface defines the namespace for your operations. Notice that it matches the capability URL you defined in muse.xml. It also defines the two operations you'll carry out, start() and stop(). Each of these operations can potentially throw an exception, which in the Web service application becomes a fault. You'll define those next.
Create the faults StopFailedFault.java and StartFailedFault.java. The faults themselves are simple Java files. Create the file <APPHOME>\src\org\apache\muse\test\derby\StartFailedFault.java, and add the code shown in Listing 7.
Listing 7. The
StartFailedFault
package org.apache.muse.test.derby;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.apache.muse.ws.resource.basefaults.BaseFault;
public class StartFailedFault extends BaseFault
{
public static final QName START_FAILED_QNAME =
new QName(DerbyControl.NAMESPACE_URI, "StartFailedFault", DerbyControl.PREFIX);
public StartFailedFault(Element arg0)
{
super(arg0);
}
public StartFailedFault(String arg1)
{
super(START_FAILED_QNAME, arg1);
}
public StartFailedFault(String arg1, Throwable arg2)
{
super(START_FAILED_QNAME, arg1, arg2);
}
public StartFailedFault(Throwable arg1)
{
super(START_FAILED_QNAME, arg1);
}
}
|
Essentially the class lets BaseFault handle problems.
Create the file <APPHOME>\src\org\apache\muse\test\derby\StopFailedFault.java, and add the code shown in Listing 8.
Listing 8. The
StopFailedFault
package org.apache.muse.test.derby;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.apache.muse.ws.resource.basefaults.BaseFault;
public class StopFailedFault extends BaseFault {
public static final QName STOP_FAILED_QNAME = new QName(DerbyControl.NAMESPACE_URI,
"StopFailedFault", DerbyControl.PREFIX);
public StopFailedFault(Element arg0) {
super(arg0);
}
public StopFailedFault(String arg1) {
super(STOP_FAILED_QNAME, arg1);
}
public StopFailedFault(String arg1, Throwable arg2) {
super(STOP_FAILED_QNAME, arg1, arg2);
}
public StopFailedFault(Throwable arg1) {
super(STOP_FAILED_QNAME, arg1);
}
}
|
Now you'll look at implementing the interface.
Create the implementation: DerbyControlImpl.java
Start by creating the directory <APPHOME>src/org/apache/muse/test/derby/impl/ and adding the file DerbyControlImpl.java. Add the code shown in Listing 9.
Listing 9. DerbyControlImpl.java
package org.apache.muse.test.derby.impl;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collection;
import java.util.Iterator;
import javax.xml.namespace.QName;
import org.apache.muse.util.MultiMap;
import org.apache.muse.ws.addressing.soap.SoapFault;
import org.apache.muse.ws.resource.impl.AbstractWsResourceCapability;
import org.apache.muse.test.derby.DerbyControl;
import org.apache.muse.test.derby.StartFailedFault;
import org.apache.muse.test.derby.StopFailedFault;
public class DerbyControlImpl extends AbstractWsResourceCapability implements
DerbyControl {
public static final QName[] PROPERTIES = { };
public QName[] getPropertyNames() {
return PROPERTIES;
}
public void initialize() throws SoapFault {
super.initialize();
}
public void start() throws StartFailedFault {
try {
Runtime.getRuntime().exec("cmd /c StartNetworkServer");
getLog().info("The derby process was started successfully.");
} catch (IOException error) {
throw new StartFailedFault("The derby process failed to start.");
}
}
public void stop() throws StopFailedFault {
try {
Runtime.getRuntime().exec("cmd /c StopNetworkServer");
getLog().info("The derby process was stopped successfully.");
} catch (IOException error) {
throw new StopFailedFault("The derby process failed to stop.");
}
}
}
|
This class, adapted like the others from the supplied sample, implements the start() and stop() functions. In each case, you want the Java run time to execute a command on the system itself to either start or stop Derby.
Now, before moving on, a few words about the command itself.
Additional information on the StartNetworkServer command
If you go to the command line, you can simply execute the statement. If you try to feed that to Runtime.exec(), however, the result depends on the system and the operating system. Because StartNetworkServer is actually a script rather than an application, you can't execute it directly; you have to feed it to the DOS application cmd instead. Additionally, on some systems, you may find that you need to use the command command /c StartNetworkServer instead.
Now you're ready to actually compile the service. This is something you can do by hand if you like, but it's much easier to use Ant with the build.xml file in Listing 10.
Listing 10. The build.xml file
<?xml version="1.0"?>
<project name="project" default="war">
<target name="init">
<basename property="NAME" file="${basedir}"/>
<property name="MUSE_HOME" value="C:/SW/muse-2.1.0-SNAPSHOT-bin"/>
<property name="MUSE_TEMPLATE" value="${MUSE_HOME}/lib/axis2"/>
<property name="BUILD_DIR" value="build"/>
<property name="JAVA_SRC_DIR" value="src"/>
<property name="JAVA_DEST_DIR" value="${BUILD_DIR}/bin"/>
<property name="WAR_FILE" value="${BUILD_DIR}/${NAME}.war"/>
<property name="LIB_DIR" value="${BUILD_DIR}/WEB-INF/lib"/>
<property name="JAR_FILE" value="${LIB_DIR}/${NAME}.jar"/>
<path id="muse.class.path">
<fileset dir="${MUSE_HOME}/modules/ws-fx-api/">
<include name="*.jar"/>
</fileset>
<fileset dir="${MUSE_HOME}/modules/ws-fx-impl/">
<include name="*.jar"/>
</fileset>
<fileset dir="${MUSE_HOME}/modules/core/">
<include name="*.jar"/>
</fileset>
<fileset dir="${MUSE_TEMPLATE}/WEB-INF/lib">
<include name="wsdl4j*.jar"/>
</fileset>
</path>
</target>
<target name="layout" depends="init, clean">
<copy todir="${BUILD_DIR}">
<fileset dir="${MUSE_TEMPLATE}">
<include name="**/*"/>
</fileset>
</copy>
<copy todir="${BUILD_DIR}/WEB-INF/services/muse/">
<fileset dir=".">
<include name="wsdl/**"/>
<include name="router-entries/**"/>
</fileset>
</copy>
<copy todir="${BUILD_DIR}/WEB-INF/services/muse/META-INF">
<fileset dir="config">
<include name="services.xml"/>
</fileset>
</copy>
<copy todir="${BUILD_DIR}/WEB-INF/services/muse">
<fileset dir="config">
<include name="muse.xml"/>
</fileset>
</copy>
<copy todir="${LIB_DIR}" flatten="true">
<fileset dir="${MUSE_HOME}/modules">
<include name="ws-fx-api/*.jar"/>
<include name="axis2/*.jar"/>
<include name="ws-fx-impl/*.jar"/>
<include name="core/*.jar"/>
</fileset>
<fileset dir="${MUSE_HOME}/lib/common">
<include name="xstream*.jar"/>
</fileset>
</copy>
</target>
<target name="java" depends="layout">
<mkdir dir="${JAVA_DEST_DIR}"/>
<javac srcdir="${JAVA_SRC_DIR}" destdir="${JAVA_DEST_DIR}"
classpathref="muse.class.path"/>
<jar basedir="${JAVA_DEST_DIR}" destfile="${JAR_FILE}">
<fileset dir="${JAVA_DEST_DIR}">
<include name="**/*.class"/>
</fileset>
</jar>
</target>
<target name="war" depends="java">
<jar destfile="${WAR_FILE}">
<fileset dir="${BUILD_DIR}">
<include name="WEB-INF/**"/>
</fileset>
</jar>
</target>
<target name="clean" depends="init">
<delete dir="${BUILD_DIR}"/>
</target>
</project>
|
Make sure that you set the value of MUSE_HOME, bold in Listing 10, to point to the actual location of your Muse installation.
Save this file in <APPHOME> as build.xml.
Finally, you can compile the Web service by opening a command-line window, changing to the <APPHOME> directory, and simply typing ant.
Following the build.xml script, Ant creates the file <APPHOME>\build\DerbyControl.war. This file contains a Web application that includes everything you need to run the Web service, including all of the appropriate JAR files. To deploy the application, copy the DerbyControl.war file to the directory <CATALINA_HOME>\webapps. Once you've done that, you can start the application server by opening a command-line window and typing %CATALINA_HOME%\bin\startup.
This command should open a new window with the Tomcat console. If you read the messages that scroll down the screen, you should see a message indicating that Tomcat is deploying the DerbyControl application.
At this point, the service is complete. Now you need a client.




