First step is to configure JMS. I will show you the steps on the Integrated WebLogic of JDeveloper.
Create a persistent Store. You can use a normal FileStore and target this to the DefaultServer.
Create a JMS Server and use the FileStore and also target this to the DefaultServer.
Create a JMS Module and target this to the DefaultServer.
Create a Sub Deployment ( part of your JMS Module ) and target this to your JMSServer.
Now you can create some resources for this JMS Module. You need to create a Connection Factory and use your Sub Deployment. Create a JMS Queue and also use the same Sub Deployment. The JNDI Names are very important you need this in your JAX-RPC Web Service Class.
The WebLogic JMS part is ready, you can restart the WebLogic Server from JDeveloper and check if you see the JNDI Resources in the DefaultServer ( Go to Servers in the WebLogic Console , Click the DefaultServer, on the top of the page there is a JNDI hyperlink )
In JDeveloper you can create a new Workspace / Project.
Create a new Java Class which will be our JAX-RPC Web Service class. Here you need to add the WLJmsTransport Annotation with the queue and connectionFactory attribute. You can't use the forward slash in the JDNI name so replace this with a dot. The rest is like a normal Web Service in JAX-WS or JAX-RPC.
package nl.whitehorses.ws.jms;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import weblogic.jws.WLJmsTransport;
@WebService(portName = "HelloWorldJMSPort",
serviceName = "HelloWorldJMSService")
@WLJmsTransport(serviceUri="HelloWorldJMSService",
contextPath="HelloWorldJMSService",
queue="jms.SoapQueue",
portName="HelloWorldJMSPort",
connectionFactory="jms.CF")
public class HelloWorld {
@WebMethod
@WebResult(name = "result")
public String sayHello(@WebParam(name = "message") String message ) {
return message;
}
}
Next step is to deploy this to the WebLogic Server. You need to do this with ANT. Add an empty build file to your project and the Weblogic jar to the ANT classpath.Open the build.xml and add the following.
<project name="webservices-hello_world" default="all">
<taskdef name="jwsc" classname="weblogic.wsee.tools.anttasks.JwscTask"/>
<target name="build-service">
<jwsc srcdir="src" destdir="deploy/helloWorldEar">
<jws file="nl/whitehorses/ws/jms/HelloWorld.java" type="JAXRPC"/>
</jwsc>
</target>
<taskdef name="wldeploy" classname="weblogic.ant.taskdefs.management.WLDeploy"/>
<property name="wls.username" value="weblogic"/>
<property name="wls.password" value="weblogic1"/>
<property name="wls.hostname" value="localhost"/>
<property name="wls.port" value="7101"/>
<property name="wls.server.name" value="DefaultServer"/>
<target name="deploy">
<wldeploy action="deploy" name="helloWorldEar" source="deploy/helloWorldEar"
user="${wls.username}" password="${wls.password}" verbose="true"
adminurl="t3://${wls.hostname}:${wls.port}"
targets="${wls.server.name}"/>
</target>
<taskdef name="clientgen" classname="weblogic.wsee.tools.anttasks.ClientGenTask"/>
<target name="client">
<clientgen wsdl="http://${wls.hostname}:${wls.port}/HelloWorldJMSService/HelloWorldJMSService?WSDL"
destdir="src"
packagename="nl.whitehorses.client.jms"
type="JAXRPC"/>
<javac srcdir="src"
destdir="classes"
includes="nl/whitehorses/client/jms/**/*.java"/>
</target>
</project>
First step is to make an deployment with the JAXRPC option. Run the build-service target. After that you can run the deploy target.If everything went well, you can go to the WebLogic deployments.
Select the Web Service and go to the Testing Tab. You can't test this Web Service with this Test Client.
Select the WSDL hyperlink and take a look at the endpoint.
The last part is to test this Web Service. For this you need to generate a Web Service Proxy client. Run the client target in ANT. After that you can make your own TestClient where you will be using these client classes.
package nl.whitehorses.client.jms;
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
import javax.xml.rpc.Stub;
import weblogic.wsee.jaxrpc.WLStub;
public class TestService {
public TestService() throws RemoteException, ServiceException {
HelloWorldJMSService service = new HelloWorldJMSService_Impl(
"http://localhost:7101/HelloWorldJMSService/HelloWorldJMSService?WSDL");
HelloWorld port = service.getHelloWorldJMSPort();
Stub stub = (Stub)port;
stub._setProperty(WLStub.JMS_TRANSPORT_JNDI_URL,"t3://localhost:7101");
try {
String result = null;
result = port.sayHello("Hello");
System.out.println("Got JMS result: " + result);
} catch (RemoteException e) {
throw e;
}
}
public static void main(String[] args) {
TestService testService;
try {
testService = new TestService();
} catch (RemoteException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
}
}
Here you can download my JDeveloper 11g Workspace.
Extra update from Ales.
When you want to use both one for SOAP/HTTP and also for SOAP/JMS you need to define a port for each communication protocol and it need to have its own service.
you can use the following logging options.
-Dweblogic.wsee.verbose=weblogic.wsee.connection.transport.jms.*
-Dweblogic.wsee.verbose= weblogic.wsee.server.jms.*
This shows which JMS listeners are instantiated and on which ports they are listening.









Nice post..I only managed to get the solution deployed using ant from the command line, after running setDomainEnv in the default domain. If I tried to run the ant tasks from JDeveloper I received the following error:
ReplyDelete"taskdef class weblogic.wsee.tools.anttasks.JwscTask cannot be found"
This may be useful for others..
Hi,
ReplyDeleteDid you update the weblogic jar in the ANT section of the project options else you will use my path to the weblogic.jar
thanks Edwin
Can you please let me know how to integrate with Maven.
ReplyDeleteThanks
PLS, tell us, how to integrate this with maven build (it is more universal).
ReplyDeleteI integrate this with maven (and ant plugin), and i have one question, how to prevent ant from making WAR file ? I whant JAR instead.
ReplyDeletePs.
I'm not ant(ology) spec :) so maybe it's obvious for You and You can help ;).
BTW, i can post You pom.xml for MAVEN project (with dependecys)
Hi,
ReplyDeletetake a look at this http://www.rgagnon.com/javadetails/java-0532.html
but I think you need a war for the servlet part and this needs to be configured in the web.xml
thanks
Can You describe how transactions works int this implementation?
ReplyDeleteYes, how transaction works ? I add some code that throws exception to Your code and messages doesn't back to queue. Why ?
ReplyDeleteHi,
ReplyDeleteOk I did not handle any exception in jax-rpc so can you follow this guide http://www.ibm.com/developerworks/xml/library/ws-tip-jaxrpc.html and try your test again.
thanks
Ok, i tested all from that Exceptions and still messages don't back to queue. I set messages redelivery limit to 3 and after that wrong messages should land in failqueue but they don't. They just disappear. Maybe I made error in code. Take a look, and pls help :) i have to make this reliable
ReplyDeletepackage example;
/*import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;*/
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import weblogic.jws.Transactional;
import weblogic.jws.WLJmsTransport;
/**
*
* @author me
*
*/
//@Session(ejbName="transactionEJB")
//@JndiName(local="transactionEJB")
@Transactional(value=true)
@WebService(portName = "HelloWorldJMSPort", serviceName =
"HelloWorldJMSService")
@WLJmsTransport(serviceUri="HelloWorldJMSService",
contextPath="HelloWorldJMSService", queue="jms.SoapQueue",
portName="HelloWorldJMSPort", connectionFactory="jms.CF")
public class HelloWorld /* implements SessionBean */{
private static final long serialVersionUID = 1L;
@WebMethod
@WebResult(name = "result")
public String sayHello(@WebParam(name = "message") String message ) {
if(message.equals("exce"))
{
throws new ANY_EXCEPTION_FROM_IBM_SITE;
}
else
return message;
}
/*@Override
public void ejbActivate() throws EJBException, RemoteException {}
@Override
public void ejbPassivate() throws EJBException, RemoteException {}
@Override
public void ejbRemove() throws EJBException, RemoteException {}
@Override
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {}*/
}
Hi,
ReplyDeleteI don't have any problems.
this was my error
public class HelloWorld {
@WebMethod
@WebResult(name = "result")
public String sayHello(@WebParam(name = "message") String message ) {
int i = 1/0;
return message;
}
}
and the stacktrace I received in the client
java.rmi.RemoteException: SOAPFaultException - FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [Failed to invoke end component nl.whitehorses.ws.jms.HelloWorld (POJO), operation=sayHello
-> Failed to invoke method
-> / by zero
] FaultActor [null] Detail [java.lang.ArithmeticException: / by zero
at nl.whitehorses.ws.jms.HelloWorld.sayHello(Unknown Source)
I also see in the monitoring of the queue the soapfault messages
I tested it with the code of this blogpost
thanks
OK, thx
ReplyDeleteThanks a lot!!
ReplyDeleteIts really helpful..
Hi,
ReplyDeleteSupporting Web Services over JMS is a common requirement since it is a reliable alternative to web service over HTTP. My question is, how can i do this via Oracle Service Bus. Suppose i have two queues, one for MessageIN and other one for MessageOUT. Now i want to call them through Web service from OSB.
Thanks
Haider
Hi,
ReplyDeleteDid you read this blogpost.
http://biemond.blogspot.com/2010/09/soap-over-jms-with-oracle-service-bus.html
Thanks
Hi,
ReplyDeleteIs it possible to rollback the Web Service transaction?
I tried to do rollback in case of some exception but the message doesn't come back to the queue.
How can I achive this behaviour?
Hi,
ReplyDeletebe careful , not to create a loop. At least add an error queue to this queue with a retry of 3 times.
I think the message is already committed when you get the message on weblogic.
you can check this WLJmsTransport annotation
@WLJmsTransport(serviceUri="HelloWorldJMSService",
contextPath="HelloWorldJMSService", queue="jms.SoapQueue",
portName="HelloWorldJMSPort",
connectionFactory="jms.CF")
thanks
Hi Edwin,
ReplyDeleteThank you for this blog, its very helpful.
I am currently implementing a SOAP/JMS webservice and I have a problem with the Queue. The messages from the client get stuck in the Queue and do not reach the Webservice.
I was wondering : Is there any configuration step needed to e.g create a Listener that handles the communication between the Queue and the Webservice?
Currently, I do the following:
1) create the Queue and the ConnectionFactory:
Queue:
Module :SOAJMSModule
name: helloWorldQueue
JNDI name : jms/helloWorldQueue
subdeployment: SOASubDeployment
JMS Server: SOAJMSServer
target: soa_server1
ConnectionFactory:
name: helloWorldCF
JNDI name: jms/helloWorldCF
2) update WSDL according to the Documentation (http://docs.oracle.com/cd/E11035_01/wls100/webserv_adv/jmstransport.html).
3) In jwsc script, I use the WLJmsTransport element:
WLJmsTransport contextPath="HelloWorld/services"
serviceUri="HelloWorldService"
portName="HelloWorldServiceJMS"
queue="jms.helloWorldQueue"
connectionFactory="jms.helloWorldCF"
Please, do you have any ideas what could go wrong?
Thank you,
Ales
Hi
ReplyDeleteif the message is in the queue then it must be in the WLJmsTransport annotation of the web services.
check the jndi names of the queue and the CF and off course the targetting of the queue and the CF.
good luck
Hi Edwin,
DeleteThanks! That is probably what I am missing : How do you I configure the "targetting of the queue and the CF"?
It is something that I need to do when creating the queue? Or, is it the WLJmsTransport annotation that should handle this?
Thank you,
Ales
Hi,
DeleteYou need to do this in the WebLogic console. You can do this with sub deployments on the jms module.
Create a jms server which is targeted to a wls server. A jms module which is targeted to the jms server .
Create a sub deployment on the jms module which is targeted to the jms server . Create the queue which uses this sub deployment .
Create a cf which points to the wls server and you are done.
On the ws you need to use the jndi names of the queue and cf and replace / by a . Do this in the annotation.
Thanks
Hi Edwin,
ReplyDeleteThank you. I resolved the problem.
It was actually something else. The issue was that I defined two ports : one for SOAP/HTTP, other for SOAP/JMS. And JMS listener was not listening on the correct one.
As I have found out, the rule is:
In order to provide a webservice available through multiple communication protocols, you need to define :
(i) a port per each communication protocol,
(ii) expose each port under a different serviceUri.
I missed the (ii).
Also, I found very useful the following logging options:
-Dweblogic.wsee.verbose=weblogic.wsee.connection.transport.jms.*
-Dweblogic.wsee.verbose= weblogic.wsee.server.jms.*
This shows which JMS listeners are instantiated and on which ports they are listening.
Thank you for all the help.
Thanks,
DeleteGreat to hear, it works for you, I added your findings to my blog.