Pages

Monday, March 24, 2008

Flex jms client with OC4J Queue ( blazeds)

In this blog I will show what you have to do to send and receive jms text messages in flex. For this I use the embedded container of jdeveloper 10.1.3.3 with the blazeds libraries and the blazeds configuration xml files( this is very easy, how to do this see this blog). I also use the j2ee container of jdeveloper 10.1.3.3 so I can use the jms queues and do the rmi jndi lookup. First we create a queue in the oc4j container. I will do it manually by editing the jms.xml in the j2ee\home\config folder. Here we add a queue and a queue connection factory.
<queue name="MyJMSQueue" location="jms/MyJMSQueue">
<queue-connection-factory location="jms/MyJMSQCF"/>
Now you can start the j2ee server and use this java code to test the queue. You have to add a lot of oc4j libraries (located in j2ee\home\ ) to get rmi jndi lookup standalone working.

package jms2;

import java.sql.Timestamp;
import java.util.Properties;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.jms.TextMessage;

import javax.naming.Context;
import javax.naming.InitialContext;


public class jmsclientoc4j {

private QueueConnection connection = null;
private QueueSession session = null;
private QueueSender sender = null;
private QueueReceiver receiver = null;
private Queue queue = null;
private long waitTime = 0;

public jmsclientoc4j() {

}

public static void main(String[] args) {
new jmsclientoc4j().execute();
}

public void tearDown() {
try {
sender.close();
receiver.close();
session.close();
connection.close();

} catch (JMSException je) {
je.printStackTrace();
} finally {
}
}


public void execute() {
setUp();
put();
get();
tearDown();
}


public void get(){

try {
javax.jms.TextMessage textMessage = (javax.jms.TextMessage)receiver.receive();
System.out.println("Receiving message [" + textMessage.getJMSMessageID() + "] enqueued at " + new Timestamp(textMessage.getJMSTimestamp()).toString());
String xmlText = textMessage.getText();
System.out.println(xmlText);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

public void put(){

String messageId = null;
String xmlData = "1111";
try {
TextMessage message = session.createTextMessage(xmlData);
sender.send(message);
} catch (JMSException jmse) {
jmse.printStackTrace();
}
}

protected void setUp() {

// Haal instellingen voor de verbinding op
String queueName = "jms/MyJMSQueue";
String queueConnectionFactoryName = "jms/MyJMSQCF";
Context ctx;

try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial","com.evermind.server.rmi.RMIInitialContextFactory");
parm.setProperty("java.naming.provider.url","ormi://localhost:23791/");
parm.setProperty("java.naming.security.principal","oc4jadmin");
parm.setProperty("java.naming.security.credentials","welcome");

ctx = new InitialContext(parm);

QueueConnectionFactory connectionFactory =
(QueueConnectionFactory)ctx.lookup(queueConnectionFactoryName);

connection = connectionFactory.createQueueConnection();
connection.start();
session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
queue = (Queue)ctx.lookup(queueName);
sender = session.createSender(queue);
receiver = session.createReceiver(queue);


} catch (JMSException je) {
throw new RuntimeException("Fout opgetreden bij het starten ",
je);
} catch (Throwable t) {
throw new RuntimeException("Fout opgetreden bij het starten ",
t);

}
}
}

Here are the blazeds configurations files, these files are located in public_html/WEB-INF/flex/. For jms we need services-config.xml for the channel defitions. You can define two jms channels one for streaming, this mean blazeds is continually connected to the queue, the other polls the queue every few seconds.
The second blazeds configuration xml is the messaging-config.xml file. In this file we define the jms adapter.
here is the service-config.xml

Here is messaging-config.xml with the jms configuration

Now we are raedy with the java side now we can go to the flex builder. first we create the flex project. Follow the pictures belows



The jms producer and consumer mxml looks like this. Here we can send text messages to the queue and the consumer automatically receive these messages and displays it on the screen.

Here is the result.

10 comments:

  1. how can i access context bean inside the one method in this adater class

    ReplyDelete
  2. Hi,

    Can you explain it a little more. What is the method.

    Thanks Edwin

    ReplyDelete
  3. Hello,

    I am trying your example with oc4j 10.1.3.4.0 and I am getting error when I ran the jmsclientoc4j. The error occurred when createQueueConnection() is executed. Here is the error snippet: Exception in thread "main" javax.jms.JMSException: [PROTOCOL ERROR] JMSRemoteServer[localhost:23791]: "OC4J JMS protocol" error, "3" is unexpected.

    Have you seen this error before? Any help is appreciated.

    Thanks.

    ReplyDelete
  4. Hi,

    Did you use the correct 10.1.3.4 oc4j libs and please check your rmi port.

    thanks

    ReplyDelete
  5. Thanks for the reply. I reference all the jar files under ${oc4jhome}\j2ee\home\lib. What other jar file should I use? Also, all the ports are defaulted. The RMI is correct because the jndi lookup part is ok. I think the problem is because of the library, as you suspected, but I don't where else to find the right library.

    Thanks

    ReplyDelete
  6. Hi

    can you use this rmi client

    http://www.oracle.com/technology/software/products/ias/htdocs/utilsoft.html

    thanks

    ReplyDelete
  7. I followed the exact steps and after deploying I get this error when I click on send:

    15:18:33,423 ERROR [[MessageBrokerServlet]] Servlet.service() for servlet MessageBrokerServlet threw exception
    javax.servlet.ServletException: non-HTTP request or response
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:854)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:235)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:190)
    at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:92)
    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.process(SecurityContextEstablishmentValve.java:126
    )
    at org.jboss.web.tomcat.security.SecurityContextEstablishmentValve.invoke(SecurityContextEstablishmentValve.java:70)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:158)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:330)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:601)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    at java.lang.Thread.run(Thread.java:595)


    Any idea why I get this, something missing in my config or installation ?

    ReplyDelete
  8. Hi

    can you do this start the OC4J Container with the following option "-Doc4j.jmx.security.proxy.off=true" Otherwise you get a java.lang.SecurityException error Unauthorized access from application to MBean.
    You can add this line in the oc4j.cmd or with Oracle AS in the opmn.xml ( folder OracleAS\opmn\conf ).

    http://biemond.blogspot.com/2008/03/deploy-blazeds-on-oc4j-oracle-as.html

    thanks

    ReplyDelete
  9. Hi Edwin

    I have been having some problem with getting a flex client to leveraging blazeds and consume a Topic in an oc4j server. Let me explain this, I have a JMS Destination defined in oracle application server. i have a tomcat environment that has blazeds running within itself. I create a simple application that tries to connect a destination defined in blazeds, which is setup to connect to the destination in the server. I am not getting any error, making this impossible to debug. Here is my tomcat log

    [BlazeDS]FlexClient created with id '504AA989-5F0F-A447-4A99-72A4B4241FDF'.
    [BlazeDS]Executed command: (default service)
    commandMessage: Flex Message (flex.messaging.messages.CommandMessage)
    operation = client_ping
    clientId = 504AA989-5F1E-F0DE-0CBA-0DDFB16C637A
    correlationId =
    destination =
    messageId = 0DF54890-D63E-482E-741A-F1C8906AD802
    timestamp = 1249596969167
    timeToLive = 0
    body = {}
    hdr(DSEndpoint) = my-polling-amf
    hdr(DSId) = nil
    hdr(DSMessagingVersion) = 1
    replyMessage: Flex Message (flex.messaging.messages.AcknowledgeMessage)
    clientId = 504AA989-5F1E-F0DE-0CBA-0DDFB16C637A
    correlationId = 0DF54890-D63E-482E-741A-F1C8906AD802
    destination = null
    messageId = 504AA989-5F28-5414-8422-09F13935AF5A
    timestamp = 1249596969167
    timeToLive = 0
    body = null
    hdr(DSId) = 504AA989-5F0F-A447-4A99-72A4B4241FDF
    hdr(DSMessagingVersion) = 1.0

    [BlazeDS]Serializing AMF/HTTP response
    Version: 3
    (Header #0 name=AppendToGatewayUrl, mustUnderstand=true)
    ";jsessionid=8E7275935860B1E9593C0399BCBE6E0D"

    (Message #0 targetURI=/1/onResult, responseURI=)
    (Externalizable Object #0 'DSK')
    (Object #1)
    DSId = "504AA989-5F0F-A447-4A99-72A4B4241FDF"
    DSMessagingVersion = 1.0
    1.249596969167E12
    (Byte Array #2, Length 16)
    (Byte Array #3, Length 16)
    (Byte Array #4, Length 16)

    [BlazeDS]Channel endpoint my-polling-amf received request.
    [BlazeDS]Deserializing AMF/HTTP request
    Version: 3
    (Message #0 targetURI=null, responseURI=/1)
    (Array #0)
    [0] = (Typed Object #0 'flex.messaging.messages.CommandMessage')
    operation = 0
    correlationId = ""
    timestamp = 0
    messageId = "374BB57F-88D2-DF0A-D887-F1C890FAFB70"
    destination = "chat-topic-jms"
    body = (Object #1)
    headers = (Object #2)
    DSEndpoint = "my-polling-amf1"
    DSId = "504AA989-5F0F-A447-4A99-72A4B4241FDF"
    timeToLive = 0
    clientId = null

    [BlazeDS]MessageClient created with clientId '504AAA16-F91C-38C7-CAE9-E2EFCCF96E
    A7' for destination 'chat-topic-jms'.
    [BlazeDS]JMS consumer for JMS destination 'jms/MRFTaskSensor' is starting.

    Can you help me out?


    Thank you
    Ashwin

    ReplyDelete
  10. Hi Edwin

    I have resolved my issue. the problem was not with my blazeds configuration. JMS server did not startup properly. It won't accept subscription requests from remote machines. For some reason, jms adapter in my bpel environment was subscribing properly. This completely threw me off, i thought the problem cannot be in the server. Well anyway, great blogs.

    Thanks Ashwin

    ReplyDelete