Wiki

Clone wiki

jummp / Remote

Creating a remote interface

This document describes the necessary steps in order to export an API from the core application to another application. The following example assume that there is a service called FooService in Core whose methods should be exported.

Exporting a Service to JMS

JMS Adapter Service

To export a service to JMS a Grails service has to be created in the jummp-plugin-jms plugin as net.biomodels.jummp.jms.FooJmsAdapterService. It is very important that this is a service and not created in src/groovy and configured as a Spring Bean. The underlying plugin is only able to handle services.

The Service needs to extend the AbstractJmsAdapter and needs to be annotated with net.biomodels.jummp.webapp.ast.JmsAdapter in order to trigger the AST transformation for code generation. The service needs to provide a static field exposes with a List as value containing 'jms'. It should not be transactional (rational: already the service is transactional) and a static String field destination with the value 'jummpFooJms' is required. Additional services can be added to the service in the normal way through autowiring.

Methods are very special when being a JMS destination. First of all each method has to return a value or the call from the calling side will time out. All methods need to be annotated with grails.plugin.jms.Queue. In order to generate some more JMS related handling code the Method needs to be annotated with net.biomodels.jummp.webapp.ast.JmsQueueMethod. The annotation takes as arguments: * isAuthenticate: if true the first parameter in the method is the authentication hash * arguments: List of Class elements for the arguments. If the authentication hash is used the String does not have to be specified.

All methods need to return def and have to take exactly one parameter def message. The message parameter is a List containing the actual values. The code to delegate the method call has to access the elements of the List and typecast them into the appropriate type. Please note that if an authentication hash is used the first element in the list is the Authentication Hash and not the first parameter. The AST transformation generates additional code to handle the authentication and the type checking of the arguments.

Example

package net.biomodels.jummp.jms

import grails.plugin.jms.Queue
import net.biomodels.jummp.webapp.ast.JmsAdapter
import net.biomodels.jummp.webapp.ast.JmsQueueMethod

@JmsAdapter
class FooJmsAdapterService  extends AbstractJmsAdapter {
    static exposes = ['jms']
    static destination = "jummpFooJms"
    static transactional = false
    /**
     * Dependency Injection of Foo Service
     */
    def fooService

    @Queue
    @JmsQueueMethod(isAuthenticate=true, arguments=[Long, String, String])
    def bar(def message) {
        return fooService.bar(message[1] as Long, message[2] as String, message[3] as String)
    }
}

Remote

Remote Interface

To access the core service from the Web Application a Remote Interface has to be defined in the jummp-plugin-remote plugin in src/groovy. The interface should be called net.biomodels.jummp.remote.RemoteFooAdapter and needs to define all methods as they are accessible from the remote application. The methods should have the same name as the core services but in the parameters it should be remembered that only Datatypes defined in the Core-API plugin can be used.

The interface does not have to consider authentication hashes: the autogenerated code takes care of such issues.

Example

package net.biomodels.jummp.remote

public interface RemoteFooAdapter {
    public Map bar(Long id)
}

Remote Service

The Remote Service is used in the web application to make the core services accessible in the Grails way by just injecting a Grails service into the controllers.

Therefore a Grails service has to be created as net.biomodels.jummp.webapp.remote.RemoteFooService. The service needs to implement the RemoteFooAdapter interface and is annotated with net.biomodels.jummp.webapp.ast.RemoteService. As a value the annotation takes the name of the Remote Adapter. The service needs to have one field of type RemoteFooAdapter with the same name starting with a lowercase letter. The service does not need to implement the interface methods - the annotation causes an AST transformation to generate delegating methods to the service's field.

Example

package net.biomodels.jummp.webapp.remote

import net.biomodels.jummp.remote.RemoteFooAdapter
import net.biomodels.jummp.webapp.ast.RemoteService

@RemoteService("RemoteFooAdapter")
class RemoteFooService implements RemoteFooAdapter {

    static transactional = true
    RemoteFooAdapter remoteFooAdapter
}

Remote JMS Adapter

To have the remote JMS Adapter a Groovy class net.biomodels.jummp.jms.remote.RemoteFooAdapterJmsImpl needs to be created in the src/groovy directory of the jummp-plugin-jms-remote plugin. The class needs to extend the AbstractJmsRemoteAdapter and implement the RemoteFooAdapter created above.

The class needs to be annotated with net.biomodels.jummp.webapp.ast.RemoteJmsAdapter and takes as a value the name of the interface, that is "RemoteFooAdapter".

The implementation of the class is straight-forward. All methods are auto-generated by the AST transformation. Only a static String field ADAPTER_SERVICE_NAME needs to be added with the value "fooJmsAdapter". A protected getter method has to be added which returns the value of the static field.

Example

package net.biomodels.jummp.jms.remote

import net.biomodels.jummp.remote.RemoteFooAdapter
import net.biomodels.jummp.webapp.ast.RemoteJmsAdapter

@RemoteJmsAdapter("RemoteFooAdapter")
class RemoteFooAdapterJmsImpl extends AbstractJmsRemoteAdapter implements RemoteFooAdapter {
    private static final String ADAPTER_SERVICE_NAME = "fooJmsAdapter"

    protected String getAdapterServiceName() {
        return ADAPTER_SERVICE_NAME
    }
}

Configuring the Remote JMS Adapter Spring Bean

To enable the Spring Bean for above created class the file JummpPluginJmsRemoteGrailsPlugin.groovy in the same plugin needs to be modified. In the doWithSpring closure the bean has to be configured in a similar way as the other beans:

fooJmsRemoteAdapter(RemoteFooAdapterJmsImpl) {
    jmsSynchronousService = ref("jmsSynchronousService")
}

Configuring Web Application

In the web application the RemoteService needs to be configured to use JMS Adapter. For that the file jummp-web-application/grails-app/conf/spring/resources.groovy needs to be edited. The beans closure contains one section for JMS. The Spring Bean for the RemoteService has to be redefined to dependency inject the platform specific remote adapter.

JMS

remoteFooService(net.biomodels.jummp.webapp.remote.RemoteFooService) {
    remoteFooAdapter = ref("fooJmsRemoteAdapter")
}

Updated