1 Reply Latest reply on Dec 24, 2012 9:51 AM by nfilotto

    Custom Rest Service

    uwew

      Hi all!

       

      As we want to use (i.e. expose) Rest services in our portlets along with GateIn we tried the following:

          - use Resteasy within a portlet war application

              - drawback: in some kind of way GateIn intercepts the Resteasy Provider which causes the custom Rest services to fail

          - use the GateIn Resource container and deploy the Rest service in an extension or in a portlet war that is part of the gatein.ear archive

              - drawback: whenever the portlet war or the extension is redeployed it triggers a redeploy of gatein.ear, which fails. Server restart is necessary.

       

      So in both solutios there are some serious problems.

       

      My questions are:

          - is there a way to deploy a rest service in gatein, where it is possible to reload the application thet contains the Rest services without triggering a redeployment of gatein.ear?

           or

          - is it possible to deploy a rest service outside GateIn in a Jboss app server and prevent GateIn to intercept the Rest provider?

       

      Is there a "best-practice" example on how to use Rest services along with GateIn?

       

      Envirnoment: GateIn3.5 Beta02 JBoss Bundle

       

       

      Kind regards,

      Uwe

        • 1. Re: Custom Rest Service
          nfilotto

          Hi,

           

          Since your issue is mainly about redeployment of rest components which is specific to the development phase, I have a workaound to propose based on the GroovyScript2RestLoader which is a component that allows you to hot deploy/undeploy easily rest components written in groovy. The idea would be to write your rest components in groovy using the solution that I will describe below as long as you are in development phase, once you know that your rest component works as expected, you convert it as a rest component written in java and you undo everything that is needed to use the GroovyScript2RestLoader.

           

          I. First we need to configure the component

           

          To do this simply creates a file at standalone/configuration/gatein/portal/portal/configuration.xml (NB: portal/portal/configuration.xml is the externalized configuration file for the portal container called "portal" that doesn't exist by default so you will need to create it) with the following content:

           

          <?xml version="1.0" encoding="ISO-8859-1"?> 
          <configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd http://www.exoplaform.org/xml/ns/kernel_1_2.xsd"
              xmlns="http://www.exoplaform.org/xml/ns/kernel_1_2.xsd">
          
              <component>
                  <type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader</type>
                  <component-plugins>
                      <component-plugin>
                          <name>add groovy rest components</name>
                          <set-method>addPlugin</set-method>
                          <type>org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoaderPlugin</type>
                          <init-params>
                              <value-param>
                                  <name>workspace</name>
                                  <value>portal-work</value>
                              </value-param>
                              <value-param>
                                  <name>node</name>
                                  <value>/script/groovy</value>
                              </value-param>
                              <properties-param>
                                  <name>MyGroovyRestComponent</name>
                                  <property name="autoload" value="true" />
                                  <!--property name="path" value="file:/my/Directory/To/The/Script/MyGroovyRestComponent.groovy" /-->
                                  <property name="path" value="classpath:/com/mycompany/rest/MyGroovyRestComponent.groovy"/>
                              </properties-param>
                          </init-params>
                      </component-plugin>
                  </component-plugins>
                  <init-params>
                      <object-param>
                          <name>observation.config</name>
                          <object type="org.exoplatform.services.jcr.ext.script.groovy.ObservationListenerConfiguration">
                              <field name="workspaces">
                                  <collection type="java.util.ArrayList">
                                      <value>
                                          <string>portal-work</string>
                                      </value>
                                  </collection>
                              </field>
                          </object>
                      </object-param>
                  </init-params>
              </component>
              <component>
                  <type>org.exoplatform.services.jcr.ext.resource.jcr.Handler</type>
              </component>
          </configuration>
          
          

          Thanks to this configuration file

          1. The component org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader will be created, started and deployed as a rest component available from the relative path "script/groovy"
          2. The GroovyScript2RestLoader will load from the classpath the file "com/mycompany/rest/MyGroovyRestComponent.groovy" and will store it into the JCR in the workspace "portal-work" into the node "/script/groovy" (a comment shows you how to configure the component to load your file from the FS directly if you prefer to set an absolute path) as source content of the component "MyGroovyRestComponent". Of course this could be changed for any any other workspace or location. If you want to configure several scripts only duplicate the properties-param block, set a new name, a new path and autoload to "true".
          3. A listener will be added to listen to any change on node of type "exo:groovyResourceContainer" in the workspace  "portal-work", to be able to automatically deploy/undeploy your components.

           

          II. Add the missing dependency

           

          once done, you will have to add a new lib under modules/org/gatein/lib/main/ that you can find from here https://repository.jboss.org/nexus/content/groups/public/org/exoplatform/core/exo.core.component.script.groovy/2.5.0-CR2/exo.core.component.script.groovy-2.5.0-CR2.jar (assuming that you use GateIn3.5 Beta02 which relies on core 2.5.0-CR2, if you want to do the same thing on newer version of gatein please make sure that you use the right version of the jar)

           

          You will have also to define this new dependency into modules/org/gatein/lib/main/module.xml by adding

          <resource-root path="exo.core.component.script.groovy-2.5.0-CR2.jar"/>
          


          III. Add your component

           

          Create a file named "MyGroovyRestComponent.groovy" under the directory "com/mycompany/rest/" with the next content and put it into a jar file into the ear file of your extention under the lib directory. For example for my quick test, I put it into gatein/extensions/gatein-wsrp-integration.ear/lib/jboss7integration.jar/ but it is of course not where you are supposed to put it.

           

          import javax.ws.rs.GET;
          import javax.ws.rs.Path;
          import javax.ws.rs.PathParam;
          
          @Path("/myRestComponent")
          public class MyGroovyRestComponent
          { 
             @GET
             @Path("/sayHello/{name}")
             public String sayHello(@PathParam("name") String name)
             {
                return "Hello " + name.toUpperCase() + " !!";
             }
          }
          
          

          IV. Test it

           

          Once everything done, start your server and test it by calling the URL http://localhost:8080/rest/myRestComponent/sayHello/world

           

          You should see something like this in your log file at the end of the startup:

          15:41:23,232 INFO  [exo.jcr.component.ext.GroovyScript2RestLoader] (MSC service thread 1-4) NodeType from configuration file: exo:groovyResourceContainer
          15:41:23,245 INFO  [exo.jcr.component.ext.GroovyScript2RestLoader] (MSC service thread 1-4) Repository name from configuration file: not configured, will be used the current one
          15:41:23,246 INFO  [exo.jcr.component.ext.GroovyScript2RestLoader] (MSC service thread 1-4) List of workspaces from configuration file: [portal-work]
          

           

          V. Modify it

           

          Assuming that your code is incorrect, instead of 'return "Hello " + name.toUpperCase() + " !!";' you would like to change it for 'return "Hello dear " + name + " !!";' and you want to add a sayGoodbye method

           

          The code would then look like this:

           

          import javax.ws.rs.GET;
          import javax.ws.rs.Path;
          import javax.ws.rs.PathParam;
          
          @Path("/myRestComponent")
          public class MyGroovyRestComponent
          { 
             @GET
             @Path("/sayHello/{name}")
             public String sayHello(@PathParam("name") String name)
             {
                return "Hello dear " + name + " !!";
             }
          
             @GET
             @Path("/sayGoodbye/{name}")
             public String sayGoodbye(@PathParam("name") String name)
             {
                return "Goodbye " + name + " !!";
             }
          }
          
          

          Once saved, launch a terminal, go in the directory you have the source of your groovy rest component and call:

           

          curl -i -v -u root:gtn -X POST --data-binary @MyGroovyRestComponent.groovy -H 'Content-type:script/groovy' http://localhost:8080/rest/private/script/groovy/update/repository/portal-work/script/groovy/MyGroovyRestComponent

           

          This command will post the new content of the component MyGroovyRestComponent from the file MyGroovyRestComponent.groovy

           

          If you re-test it, you should be able to see the new result of the method sayHello and you should be able to call sayGoodbye.

           

          WARNING 1: this is a workaround and must be considered as it is.

          WARNING 2: if you want to use this solution in production you can but please make sure that you set autoload to false for all your components and you did not put any init-params in the configuration of the GroovyScript2RestLoader to prevent any malucious user to modify the content of your scripts.

          WARNING 3: the content of the script is persisted into the JCR, so make sure that you dropped the DB before re-starting your AS otherwise if the content of the script has changed it will ignore it as it will consider the component has already deployed, you will need to update it manually using the curl command described in part V.

           

          More details about the GroovyScript2RestLoader can be found here http://docs.jboss.org/exojcr/1.15.0-GA/developer/en-US/html_single/#WS.GroovyScripts