Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Apache Derby resources from the Web services perspective, Part 3: Manage Apache Derby using Web Services Distributed Management

David Medinets (david.medinets@gmail.com), Software Consultant, Eclectic Consulting
David Medinets has been programming since 1980, when he started with a TRS-80 Model 1. He still fondly remembers the days when he could cross-wire the keyboard to create funny-looking characters on the display. Since those days, he has spent time debugging the Emacs text editor on UNIX® machines, working on VAXen, and building cutting-edge Web applications (think Toys"R"Us and 7,000 simultaneous users in 1999). David is married to Kathryn and lives in Fairfax, Virginia. He runs Eclectic Consulting and has authored books on Perl, PHP, and BASH. He also runs the CodeBits.com site.

Summary:  So far in this three-part tutorial series about the concept of WS-resources and the Web Services Resource Framework (WSRF), you've created a Person resource and learned how to use WS-Notifications with it. This final installment shows you how to look at WS-Resources from a different perspective -- that of a tangible item rather than a set of information. You'll create a Web service to control the Apache Derby database you've been using throughout this project as well as the client that treats Derby as a WS-Resource.

View more content in this series

Date:  23 Mar 2007
Level:  Intermediate PDF:  A4 and Letter (80 KB | 26 pages)Get Adobe® Reader®

Activity:  9589 views
Comments:  

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.

Set the class path

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.

Compile the service

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.


Deploy the service

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.

4 of 9 | Previous | Next

Comments



static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Open source, Information Management, SOA and Web services
ArticleID=204007
TutorialTitle=Apache Derby resources from the Web services perspective, Part 3: Manage Apache Derby using Web Services Distributed Management
publish-date=03232007
author1-email=david.medinets@gmail.com
author1-email-cc=ruterbo@us.ibm.com