4.
Adding a new operation
Up one level
Adding a new operation
If you create some resources and then look at the service's administration page (the one where you configured the trusted management services), you will see that each resource is listed along with its PBAC process state. We will now add a SOAP operation called check on each resource, which says how many times it has been called since the resource was created.
There is a single Java interface file, called SampleResource.java, listing public operations on the sample resources. All resources shared by both the client and the service (interfaces and Java beans for any complex types) go in the sample-common project.
- Edit gria-devkit-5.2/sample/common/src/java/sample/SampleResource.java and add the new operation
to the interface:
@WebMethod
int check() throws RemoteException; -
Build the jar file by running the command mvn install from the gria-devkit-5.2/sample/common directory.
Recompiling requires installing Apache Maven version 2.0.7, which you can get from the Maven web-site.
Implementing the operation (client)
There is no need to write any code to implement the interface, as a suitable default implementation will be generated automatically. However, we do need to edit sample/client/src/java/sample/client/SampleClientPlugin.java to extend the client's menu with the new operation:
- In showPopupMenu(), add a new menu item for items of type
SampleConversation:
} else if (SampleConversation.class.isAssignableFrom(itemClass)) {
menu.add(new Action(browser, items, "Check") {
public void dispatch(Object sample) throws RemoteException {
int count = ((SampleConversation) sample).check();
JOptionPane.showMessageDialog(browser, "Calls to check: " + count);
}
});
}
Recompile the client by running the command mvn clean install in the sample/client directory.
To test it, copy the jar file from the sample/client/target directory to the client's conf/plugins directory as before and restart the client. You should find a new choice on the menu:
The new check operation appears on the menu
Of course, the operation won't actually work yet because it hasn't been added to the service. If you try, you will get this error message:
Operation "check" not in WSDL for endpoint https:/.../SampleResource
Implementing the operation (service)
Before adding the operation itself, we'll need a place to store each resource's counter. We'll do this by editing the sample/service/src/java/sample/SampleResourceBean.java to add a new field in the usual Java way:
private int checkCounter = 0;
public Integer getCheckCounter() {
return checkCounter;
}
public void setCheckCounter(Integer checkCounter) {
if (checkCounter == null)
checkCounter = 0;
this.checkCounter = checkCounter;
}
Note that we use Integer instead of int for the getter and setter methods because we already have some resources in the database without a counter. Hibernate will use null for the counter value of these old resources, which we interpret as zero, allowing a smooth upgrade.
In addition, we need to tell hibernate to store this field in the database, which we do by adding an element to SampleResourceBean.hbm.xml (e.g. just under the label property):
<property name="label"/>
<property name="checkCounter"/>
We will now add the SOAP operation to the service:
-
Edit sample/service/src/java/sample/impl/SampleResourceImpl.java to add the implementation of the operation:
public int check() throws RemoteException {
String conversationID = getConversationFromContext();
Session session = factory.openSession();
try {
SampleResourceBean resource = getResource(session, conversationID);
Transaction tx = session.beginTransaction();
int newValue = resource.getCheckCounter() + 1;
resource.setCheckCounter(newValue);
tx.commit();
return newValue;
} finally {
session.close();
}
}Here, we get the ID of the resource from the message context and use it to get the resource's bean from the database. Then we increment the counter, commit the new value to the database, and return the value to the client.
Note that PBAC locks the resource automatically during the operation, so we don't need to worry about concurrent updates to the counter here.
- Recompile with the command mvn install in the top-level gria-devkit-5.2 directory.
-
Undeploy the old war and deploy the new war/target/sample.war. You can do this using the usual Tomcat mechanism. You'll have to tell it where your configuration directory is again and then restart Tomcat.
Click on the List of services link at the top of the web page and you should see your new operation listed.
Restart the client (so that it downloads the updated WSDL). Attempting to invoke the operation from the client will now display a different error message:
InvalidActionException: Unknown action 'check'
We need to update the access control policy to state that the owner of a resource is able to invoke the check operation when the resource is in the ready state:
- Go to the Access control page (click on the link at the top of the web page).
- Select http://SAMPLE/2006/SampleResourceType and get the policy by clicking on Download Policy.
- Edit it, by adding the new operation to the ready state:
<state name="ready"> <operation name="check"> <process-role name="owner"/> </operation>
- Using the web interface, undeploy the old policy and upload the new version.
Test the new policy using the client. You should now be able to see the counter:

The new policy is stored in the service's database, so it will still be there when
you restart. However, if you undeploy it and then go back to the main screen, the
original default will be redeployed. To make the new policy the default for
your service, save it as war/src/main/webapp/WEB-INF/classes/sample-policy.xml, overwriting the old
one, and rebuild the service war.
Automatic war redeployment
Restarting Tomcat and reconfiguring the service each time you change something can get annoying, so you may like to automate the process. You can use the Maven Cargo plug-in for this.
-
In your Maven ~/.m2/settings.xml file, enter the login details for a Tomcat user with the manager role, e.g.:
<settings>
<profiles>
<profile>
<id>tomcat</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<tomcat-username>admin</tomcat-username>
<tomcat-password>admin</tomcat-password>
<tomcat-url>http://localhost:8080/manager</tomcat-url>
</properties>
</profile>
<profiles>
</settings> - Copy <tomcat dir>/webapps/sample/WEB-INF/classes/service-config.xml into your configuration directory (e.g. as /etc/grid-sample/service-config.xml).
- Symlink your configuration directory to war/src/preconfigured.
- Now you can build and deploy a pre-configured war with:
$ cd war
$ mvn clean install -Predeploy,preconfigured
Note: Tomcat is very bad at freeing memory when undeploying webapps, so you should restart it from time to time, to avoid getting "PermGen space" errors.
