A user on GlassFish Forum tried invoking a JAX-WS Web service from a Rails application and faced some issues. This Tip Of The Day (TTOD) will discuss the different approaches and shows their current status.
A Rails app can be deployed on GlassFish in 3 different ways:
- Directory Deployment in GlassFish v3 Server – TOTD #72 explains how to deploy a trivial Rails application (with just a scaffold) on GlassFish v3 server. Even though the blog uses a Rails application, any Rack-based application can be deployed on the server. This server is also the Reference Implementation for Java EE 6 and can also run Grails and Django applications.
- Directory Deployment using light-weight GlassFish Gem – GlassFish Gem is a light-weight version of the full-blown server and is stripped to run, just like the server, any Rack-based application such as Merb, Rails, and Sinatra. TOTD #70 shows how to deploy the same application using GlassFish Gem.
- WAR file in GlassFish v2.x or v3 – TOTD #73 explains how to deploy a Rails application as WAR file on GlassFish v2. The JNDI connection pooling part of the blog may be skipped to simplify the steps but the concepts are still valid. TOTD #44 shows how to do JNDI connection pooling for GlassFish v3. As GlassFish v2 has in-built support for session replication, TOTD #92 demonstrate how Rails application can leverage that functionality.
Now lets get to the issue reported by the user using these 3 deployment models.
First, lets deploy a simple Web service endpoint and generate a JAR file of the client-side artifacts:
- This blog will use a simple Web service as defined in screencast #ws7. The Web service endpoint looks like:
package server; import javax.jws.WebService; /** * @author arungupta */ @WebService() public class HelloService { public String sayHello(String name) { return "Hello " + name; } }
- Generate Web service client-side artifacts as:
~/samples/v3/rails/webservice/tmp >wsimport -keep http://localhost:8080/HelloWebService/HelloServiceService?wsdl parsing WSDL... generating code... compiling code...
- Create a Web service client jar file as:
jar cvf wsclient.jar ./server
Now lets write a Rails application and invoke this Web service:
- Create a simple Rails application as:
jruby -S rails webservice
Optionally you may specify "-d mysql" to use MySQL database. Or better un-comment the following line:
# config.frameworks -= [ :active_record, :active_resource, :action_mailer ]
in "config/environment.rb" as no database interaction is required.
- Create a controller and view as:
jruby script/generate controller home index
- Update the Controller in "app/controllers/home_controller.rb" as:
include Java class HomeController < ApplicationController def index service = Java::server.HelloServiceService.new port = service.getHelloServicePort @result = port.sayHello("Duke") end end
- Change the View in "app/views/home/index.html.erb" as:
<h1>Home#index</h1%gt; <p>Find me in app/views/home/index.html.erb</p> <%= @result %>
Now lets deploy this Web service using the 3 different deployment models mentioned above.
GlassFish v3 allows a directory-based deployment of Rails applications. This application needs to locate the Web service client classes. The "wsclient.jar" can be copied to the "lib" directory of Rails application ("webservice/lib" in our case), "domains/domain1/lib/ext" or "JRUBY_HOME/lib". The library can also be passed during deployment using "–libraries" switch. None of this approach seem to work correctly as explained in issue# 11408. So for now, invoking a JAX-WS Web service from a Rails application deployed directly on GlassFish v3 is not possible, at least until the bug is fixed.
In order to deploy the same application using GlassFish Gem, you can copy "wsclient.jar" to the "lib" directory of your Rails application. And also add the following line to "app/controllers/home_controller.rb":
require 'lib/wsclient.jar'
Alternatively you can copy it to "JRUBY_HOME/lib" directory if this Web service client is accessed my multiple applications. In this case there is no need to add any "require" statement to your Controller. Anyway, running the application as:
jruby -S glassfish
and accessing "http://localhost:3000/home/index" shows the following output:
And finally as explained in TOTD #73, bundle up your original Rails application as WAR and then deploy on GlassFish v3 as:
asadmin deploy webservice.war
Make sure to copy "wsclient.jar" to the "lib" directory of your Rails application and then Warbler will copy it to "WEB-INF/lib" of the generated WAR file. The output is shown as below:
So if you want to invoke a Metro/JAX-WS Web service from a Rails application, then run your Rails application using GlassFish Gem or deploying as a WAR file. It’ll work on GlassFish v3 server when issue# 11408 is fixed.
Here are some additional links:
- TOTD #104 also shows how popular Rails applications such as Redmine, Typo, and Substruct can be easily deployed on GlassFish.
- Rails applications can be easily clustered using Apache + mod_proxy or nginx.
A complete archive of all the TOTDs is available here.
Technorati: totd glassfish v3 jruby rails webservice jax-ws metro
Related posts:- JRuby-on-Rails deployed on GlassFish – Success Story
- TOTD #130: Invoking a OSGi service from a JAX-WS Endpoint – OSGi and Enterprise Java
- Creating and Invoking a Web service using GlassFish in NetBeans, IntelliJ, and Eclipse – Part 1
- TOTD #4: How to convert a Session EJB to a Web service ?
- TOTD #150: Collection of GlassFish, NetBeans, JPA, JSF, JAX-WS, EJB, Jersey, MySQL, Rails, Eclipse, and OSGi tips