java.lang.ClassCastException: Solace QueueProxy cannot be cast to Weblogic DestinationImpl

SHADOW
SHADOW Member Posts: 5
Hey Guys,

I was recently introduced to Solace and am trying to deploy a sample Pub/Sub application using JMS API on a local Weblogic server but ran into this class cast error which I cant seem to find a solution for.

I have created a topic "MyTopic" which is subscribed by a queue, "MyQueue" and also configured the JNDI names and message_vpn settings on Solace Web Console as per requirement. Then I deployed a Resource Adapter jar on my local weblogic server with the necessary Connection Factory and other credentials. So the setup so far is:

At Solace -> MyVpn:
"JNDI/Sol/mytopic" has physical name "MyTopic"
"JNDI/Sol/myqueue" has physical name "MyQueue"

At Weblogic, the Connection Factory and Destination configurations in "weblogic-ra.xml" file (apart from user credentials, url, etc.) are as follows:
```
<admin-objects>
<admin-object-group>
<admin-object-interface>javax.jms.Queue</admin-object-interface>
<admin-object-instance>
<jndi-name>JNDI/J2C/my/queue</jndi-name>
<properties>
<property>
<name>Destination</name>
<value>JNDI/Sol/myqueue</value>
</property>
</properties>
</admin-object-instance>
</admin-object-group>
<admin-object-group>
<admin-object-interface>javax.jms.Topic</admin-object-interface>
<admin-object-instance>
<jndi-name>JNDI/J2C/my/topic</jndi-name>
<properties>
<property>
<name>Destination</name>
<value>JNDI/Sol/mytopic</value>
</property>
</properties>
</admin-object-instance>
</admin-object-group>
</admin-objects>
<outbound-resource-adapter>
<connection-definition-group>
<connection-factory-interface>javax.jms.ConnectionFactory</connection-factory-interface>
<connection-instance>
<jndi-name>JNDI/J2C/CF</jndi-name>
<connection-properties>
<transaction-support>NoTransaction</transaction-support>
<properties>
<property>
<name>ConnectionFactoryJndiName</name>
<value>JNDI/Sol/CF</value>
</property>
<property>
<name>ConnectionValidationEnabled</name>
<value>true</value>
</property>
</properties>
</connection-properties>
</connection-instance>
</connection-definition-group>
</outbound-resource-adapter>
```

At the application level, I have created a EJB project with a consumer MDB that tries to read messages published on "MyTopic" by a separate Producer Java application. The code is as follows:

[ConsumerMDB.java]
```
package com.solace.ejb;
import java.util.Hashtable;
import javax.ejb.MessageDriven;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@MessageDriven
public class ConsumerMDB implements MessageListener {
private final String QUEUE_JNDI_NAME = "JNDI/J2C/my/queue";
private final String CONNECTION_FACTORY_JNDI_NAME = "JNDI/J2C/CF";
public void onMessage(Message message) {
if (message instanceof TextMessage) {
try {
TextMessage textMessage = (TextMessage) message;
System.out.println("Received message: " + textMessage.getText());
message.acknowledge();
}
catch (JMSException e) {
e.printStackTrace();
}
}
}
public void initialize() throws NamingException {
try {
Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
InitialContext initialContext = new InitialContext(env);
ConnectionFactory connectionFactory = (ConnectionFactory) initialContext.lookup(CONNECTION_FACTORY_JNDI_NAME);
Connection connection = connectionFactory.createConnection();
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue queue = session.createQueue(QUEUE_JNDI_NAME);
MessageConsumer consumer = (MessageConsumer) session.createConsumer(queue);
consumer.setMessageListener(this);
connection.start();
Thread.sleep(10000);
} catch (JMSException | InterruptedException e) {
e.printStackTrace();
}
}
public void cleanup() {
try {
if (messageConsumer != null) {
messageConsumer.close();
}
if (session != null) {
session.close();
}
if (connection != null) {
connection.close();
}
} catch (JMSException e) {
e.printStackTrace();
}
}
}
```

[ejb-jar.xml]
```
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"
version="3.2">
<enterprise-beans>
<message-driven>
<ejb-name>ConsumerMDB</ejb-name>
<ejb-class>com.solace.ejb.ConsumerMDB</ejb-class>
</message-driven>
</enterprise-beans>
</ejb-jar>

```

[weblogic-ejb-jar.xml]
```
<?xml version='1.0' encoding='UTF-8'?>
<weblogic-ejb-jar xmlns="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-ejb-jar
http://xmlns.oracle.com/weblogic/weblogic-ejb-jar/1.0/weblogic-ejb-jar.xsd ">
<weblogic-enterprise-bean>
<ejb-name>ConsumerMDB</ejb-name>
<message-driven-descriptor>
<destination-jndi-name>JNDI/J2C/my/queue</destination-jndi-name>
</message-driven-descriptor>
</weblogic-enterprise-bean>
</weblogic-ejb-jar>

```

Now when I am deploying this consumer jar on MyServer I am getting this error without the flow even reaching my code (which might as well be flawed):

<Warning><The Message-Driven EJB ConsumerMDB is unable to connect to the JMS destination or bind to JCA resource adapter JNDI/J2C/my/queue. The connection failed after 2 attempts. The MDB will attempt to reconnect/rebind every 10 seconds. This log message wil<The Message-Driven EJB ConsumerMDB is unable to connect to the JMS destination JNDI/J2C/my/queue. The Error was:
java.lang.ClassCastException: com.solacesystems.jms.ra.outbound.QueueProxy cannot be cast to weblogic.jms.common.DestinationImplStack Trace for RuntimeException was:java.lang.ClassCastException: com.solacesystems.jms.ra.outbound.QueueProxy cannot be cast to weblogic.jms.common.DestinationImpl
at weblogic.jms.client.JMSSession.createConsumer(JMSSession.java:2882)
at weblogic.jms.client.JMSSession.createConsumer(JMSSession.java:2860)
at weblogic.jms.client.JMSSession.createReceiver(JMSSession.java:2766)



I am new to this framework and might have possibly messed up on the configuration or maybe even approaching it incorrectly.

However, any help or guidance from the fellow community members on what is going wrong here is greatly appreciated. Thanks.

Answers

  • Aaron
    Aaron Member, Administrator, Moderator, Employee Posts: 634 admin

    Hi @SHADOW… I don't know much about WebLogic so hopefully someone more knowledgeable says something. But: have you created an actual queue in Solace called MyQueue..? Although I don't think that would help with a Java cast exception.

    Also, not sure why the code formatting didn't work… I can see your three backticks. Make sure you hit [ENTER] before the three backticks, not Shift+ENTER as that's not a full paragraph break.

    I know we have some CodeLab tutorial for Weblogic, might be a bit dated, but maybe this could help? https://codelabs.solace.dev/codelabs/weblogic-app-server

  • SHADOW
    SHADOW Member Posts: 5

    Hi @Aaron ,

    Yes I have created an actual queue ("MyQueue") at Solace. I had initially referenced the Weblogic Guide you have mentioned but couldn't get it to work because of the same error. I'm guessing the weblogic-ejb-jar.xml is at fault here maybe?

    PS: yeah code formatting was not visible to me as well for some reason even after pressing [ENTER]. It worked in my other post though.

  • SHADOW
    SHADOW Member Posts: 5

    UPDATE:

    I tried a bunch to get this to work but unfortunately couldn't. So I finally decided to just forego this Message Driven Bean approach and reworked the whole thing by simply implementing a Message Listener in the class file. And whaddya know the simplest solution is the one that works.

    This is the modified code:

    package main;
    
    //<Imports here>
    
    public class TopicConsumer implements MessageListener {
    
    private ConnectionFactory connectionFactory;
    private Connection connection;
    private Session session;
    private MessageConsumer messageConsumer;
    private final String CONNECTION_FACTORY_JNDI_NAME = "JNDI/J2C/CF";

    TopicConsumer() throws InterruptedException {
    initialize();
    }

    @Override
    public void onMessage(Message message) {
    try {
    if (message instanceof TextMessage) {
    System.out.printf("TextMessage received: '%s'%n", ((TextMessage) message).getText());
    } else {
    System.out.println("Message received.");
    System.out.printf("Message Content:%n%s%n", SolJmsUtility.dumpMessage(message));
    }

    // ACK the received message manually because of the set SupportedProperty.SOL_CLIENT_ACKNOWLEDGE above
    message.acknowledge();

    } catch (JMSException ex) {
    System.out.println("Error processing incoming message.");
    ex.printStackTrace();
    }

    }

    public void initialize() throws InterruptedException {
    try {
    Hashtable<String, Object> env = new Hashtable<>();
    env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
    InitialContext initialContext = new InitialContext(env);
    connectionFactory = (ConnectionFactory) initialContext.lookup(CONNECTION_FACTORY_JNDI_NAME);

    System.out.println("Connection Factory " + connectionFactory + " established");

    connection = connectionFactory.createConnection();
    System.out.println("Connection " + connection + " created");

    session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    Queue queue = session.createQueue("MyQueue");

    messageConsumer = session.createConsumer(queue);
    messageConsumer.setMessageListener(this);

    connection.start();
    System.out.println("Awaiting message...");

    } catch (NamingException | JMSException e) {
    e.printStackTrace();
    }
    finally {
    try{
    connection.stop();
    messageConsumer.close();
    session.close();
    connection.close();
    } catch (Exception e) {

    System.err.println("Error sending message: " + e.getMessage());
    e.printStackTrace();

    }

    }
    } }

    Similar to the case with my producer code I directly gave the actual destination name instead of doing a JNDI lookup while creating the Queue. I don't know why i tried to make it extra complicated with the MDB.

    Anyways hope this helps anyone else facing the issue. Cheers !!