JMS Topic sender is throwing exception Null pointer exception for the connection Factory - nullpointerexception

I am trying to make a simple JMS topic sender.In the code its returning error in the very first line ,where I am creating a connection using ConnectionFactory.
public class TopicSender {
#Resource(lookup = "ConnectionFactoryTest1")
private static ConnectionFactory connectionFactory;
#Resource(lookup ="myTopic")
private static Topic topic;
public static void main(String[] args) throws JMSException{
//Create a connection
Connection connection =connectionFactory.createConnection();
//Get a session
Session session =connection.createSession();
MessageProducer producer=session.createProducer(topic);
//Send a test message to the topic
TextMessage message = session.createTextMessage();
message.setText("This test message sent at" + new Date());
producer.send(message);
session.close();
connection.close();
}
Console output:
Exception in thread "main" java.lang.NullPointerException
at com.aman.JMS.Test1.TopicSender.main(TopicSender.java:23)
Can anybody help me understand why I am getting this exception.
I am using GlassFish server.

Related

RabbitMQ request/response "RabbitTemplate is not configured as listener"

I'm testing request/response pattern with Spring-AMQP rabbitmq implementation and I can't make it work...
I've got configured following artifacts:
test_exchange with greeting queue. Routing key = greeting
reply_exchange with replies queue. Routing key = replies
#Bean
public ConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory =
new CachingConnectionFactory("....IP of broker...");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
return connectionFactory;
}
#Bean
public Queue greeting() {
return new Queue("greeting");
}
#Bean
public Queue replies() {
return new Queue("replies");
}
MessageListener receiver() {
return new MessageListenerAdapter(new RabbitMqReceiver(), "onMessage");
}
#Bean
public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory, Queue replies) {
RabbitTemplate template = new RabbitTemplate(connectionFactory);
template.setExchange("test_exchange");
template.setRoutingKey("greeting");
template.setReplyAddress("reply_exchange"+"/"+replies.getName());
template.setReplyTimeout(60000);
return template;
}
#Bean
public SimpleMessageListenerContainer replyContainer(ConnectionFactory connectionFactory,
RabbitTemplate rabbitTemplate, Queue replies) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setMessageListener(rabbitTemplate);
container.setQueues(replies);
return container;
}
#Bean
public SimpleMessageListenerContainer serviceListenerContainer(
ConnectionFactory connectionFactory) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueues(greeting());
container.setMessageListener(receiver());
return container;
}
I was following example at github, but it crashes with:
Caused by: java.lang.IllegalStateException: RabbitTemplate is not configured as
MessageListener - cannot use a 'replyAddress': reply_exchange/replies
Documentation says:
Starting with version 1.5, the RabbitTemplate will detect if it has been configured as a MessageListener to receive replies. If not, attempts to send and receive messages with a reply address will fail with an IllegalStateException (because the replies will never be received).
This is excellent, but how RabbitTemplate does that? How does it detect if it's configured as MessageListener?
thanks in advance
PS: Send code:
public void send() {
Message message = MessageBuilder.withBody("Payload".getBytes())
.setContentType("text/plain")
.build();
Message reply = this.template.sendAndReceive(message);
System.out.println("Reply from server is: "+new String(reply.getBody()));
}
When the reply container starts, it detects that the template is ListenerContainerAware and calls expectedQueueNames() to retrieve the reply queues (or null if the replyAddress has the form exch/rk); if a non-null result is returned, the container checks that the queue is correct; if exch/rk is the reply address, you would get this
logger.debug("Cannot verify reply queue because it has the form 'exchange/routingKey'");
This method unconditionally sets the isListener boolean which avoids that exeption. So it seems like the container hasn't started before you sent your message - are you sending before the context is fully initialized?
Note that since RabbitMQ implemented direct reply-to, it is generally not necessary any more to use a reply container (unless you want HA reply queues or need an explicit reply queue for some other reason). Direct reply-to removed the performance problem that drove us to implement the reply container mechanism.
Gary, your intuition was perfect, as always.
I changed my send code from:
#SpringBootApplication
public class App
{
#Bean(initMethod="send")
public RabbitMqSender sender() {
final RabbitMqSender sender = new RabbitMqSender();
return sender;
}
public static void main(String[] args) throws Exception {
SpringApplication.run(App.class, args);
}
}
to:
#SpringBootApplication
public class App
{
public static void main(String[] args) throws Exception {
final ConfigurableApplicationContext configAppContext = SpringApplication.run(App.class, args);
final RabbitMqSender sender = configAppContext.getBean(RabbitMqSender.class);
sender.send();
}
}
to ensure to be sending when all beans are ready and request/response WORKS EXCELLENT!
Yes, I will definitelly try Direct-TO pattern as well.
Thanks you Gary for help.
regards
Tomas

Do we need to start ActiveMQ when configuring through spring?

I get connection refused errors when i try to test activemq using spring jms integration. Do i need to start the activemq server or something? From my understanding spring would have all the methods to start the active mq when i setup the brokerconnction
source
#SpringBootApplication
#EnableJms
public class Application {
#Bean
public DefaultJmsListenerContainerFactory myJmsContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory());
return factory;
}
#Bean
public JmsTemplate jmsTemplate(){
JmsTemplate jmsTemplate = new JmsTemplate();
jmsTemplate.setDefaultDestination(new ActiveMQQueue("jms.queue"));
jmsTemplate.setConnectionFactory(connectionFactory());
return jmsTemplate;
}
#Bean
public ActiveMQConnectionFactory connectionFactory(){
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory("tcp://:61616");
activeMQConnectionFactory.setBrokerURL("tcp://localhost:61616");
return activeMQConnectionFactory;
}
public static void main(String[] args){
// Clean out any ActiveMQ data from previous run
FileSystemUtils.deleteRecursively(new File("activemq-data"));
// Launch the application
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
// Send a message
MessageCreator messageCreator = new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
return session.createTextMessage("ping!");
}
};
JmsTemplate jmsTemplate = context.getBean(JmsTemplate.class);
System.out.println("Sending a new message");
jmsTemplate.send("mailbox-destination", messageCreator);
}
}
Error
Exception in thread "main" org.springframework.jms.UncategorizedJmsException: Uncategorized exception occured during JMS processing; nested exception is javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused
at org.springframework.jms.support.JmsUtils.convertJmsAccessException(JmsUtils.java:316)
at org.springframework.jms.support.JmsAccessor.convertJmsAccessException(JmsAccessor.java:169)
at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:497)
at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:580)
at org.blanc.whiteboard.jms.Application.main(Application.java:67)
Caused by: javax.jms.JMSException: Could not connect to broker URL: tcp://localhost:61616. Reason: java.net.ConnectException: Connection refused
If you use a vm://localhost URL, an in-memory broker will be started on the vm transport; if you use the tcp://... url you need to start an external broker, or add a broker bean to your application.

Send Message on embedded activeMQ message server in glassfish

I developed a Java EE application (on GlassFish) with an embedded activeMQ message server. I can send messages to my Message Driven Bean. Now I'd like to send message back to another topic over my activeMQ broker.
No message is delivered to the topic "answer". I see it on the activeMQ-web-frontend and no exception is thrown.
I don't see the problem. Can somebody give me a tip where I can search?
Here my classes:
#MessageDriven(activationConfig = {
#ActivationConfigProperty(propertyName = "destination", propertyValue = "amqmsg"),
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic") }, mappedName = "amqmsg")
#TransactionManagement(TransactionManagementType.BEAN)
public class TopicMB implements MessageListener {
#Inject
private MessageSender messageSender;
private static final Logger logger = LoggerFactory.getLogger(TopicMB.class);
public void onMessage(Message message) {
messageLogger.log(message);
try {
messageSender.send("antwort");
} catch (Exception e) {
logger.error(e.getLocalizedMessage());
e.printStackTrace();
}
}
}
And my MessageSender. amqpool injects the connector connection pool for acitveMQ.
#Stateless
public class MessageSender {
private static final Logger logger = LoggerFactory
.getLogger(MessageSender.class);
#Resource(name = "amqpool")
private ConnectionFactory connectionFactory;
private static String subject = "answer";
public void send(String text) throws JMSException {
Connection connection = connectionFactory.createConnection();
connection.start();
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
Destination destination = session.createTopic(subject);
MessageProducer producer = session.createProducer(destination);
producer.setDeliveryDelay(DeliveryMode.PERSISTENT);
TextMessage message = session.createTextMessage("antwort");
// Here we are sending the message!
producer.send(message);
session.close();
}
}
If the message is seen on the webconsole, then it sounds like there is no consumer on the Topic.
Note that Topics never store messages - subscriptions to Topics store messages. Non-durable subscriptions (the default) are only active while the consumer is connected and actively subscribed to the Topic. Durable subscriptions can hold messages while the consumer is not connected.
So, is there a consumer on the Topic at the time the message is sent to it, or a registered durable subscription on the Topic?

How can I throttle a WCF MSMQ endpoint?

I'm new to WCF and just learning how to get a client to talk to a host (both in console applications) using MSMQ.
I want to be able to send messages from client to host and have the host pick them up immediately or, if the host is stopped, to continue where it left off when it is restarted.
I've got this almost working but I find that when I restart the host with ten messages in the queue, the messages are not processed in the queue order. I assume there's some multithreading going on that makes them appear out of order. I'd like to be able to limit the WCF service to processing one message at a time to stop this happening (unless there's a better solution).
It's essential to a system that I'm about to work on that the MSMQ messages are processed in order and not in parallel.
The code for my service contract is:
[ServiceContract(Namespace = "http://www.heronfoods.com/DemoService")]
public interface IDemoService
{
[OperationContract(IsOneWay = true)]
void SendMessage(string message);
}
For the Service contract implementation I've got this. (The console output is because this is a demo app for me to learn from):
public class DemoService : IDemoService
{
public void SendMessage(string message)
{
Console.WriteLine("{0} : {1}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), message);
}
}
My host application is a console application with the following code:
class Program
{
static void Main(string[] args)
{
Console.Title = "WCF Host";
using (var host = new ServiceHost(typeof(Library.DemoService)))
{
var endpoint = new ServiceEndpoint(
ContractDescription.GetContract(typeof(Library.IDemoService)),
new NetMsmqBinding(NetMsmqSecurityMode.None),
new EndpointAddress("net.msmq://localhost/private/test"));
host.AddServiceEndpoint(endpoint);
host.Open();
Console.WriteLine("Host Active");
Console.ReadLine();
}
}
}
The client is equally simple:
class Program
{
static void Main(string[] args)
{
Console.Title = "WCF Client";
IDemoService proxy = ChannelFactory<IDemoService>.CreateChannel(
new NetMsmqBinding(NetMsmqSecurityMode.None),
new EndpointAddress("net.msmq://localhost/private/test")
);
do
{
string msg = Console.ReadLine();
if (msg=="")
break;
else
proxy.SendMessage(msg);
} while (true);
}
}
I am assuming your queue is not transactional.
While I'm not certain there's a way to throttle netMsmqBinding to a single thread, you shouldn't need to apply this restriction.
To guarantee ordered delivery you only need to make your queue transactional and then apply the exactlyOnce attribute to the netMsmqBinding configuration.
See example here.

Error Object reference not set to an instance of an object on WCF Service

I am currently developing a WCF Publish Subscribe service. My Service has the following code,
public void PublishPost(string postSampleData)
{
PostChangeEventArgs e = new PostChangeEventArgs();
e.PostData = postSampleData;
PostChangeEvent(this, e);
}
and the code for the postChangeEvent is
public class PostChangeEventArgs : EventArgs
{
public string PostData;
}
and in my client file, i wrote this code in the main method,
class Program : IPostingContractCallback
{
static void Main()
{
InstanceContext site = new InstanceContext(null, new Program());
PostingContractClient client = new PostingContractClient(site);
WSDualHttpBinding binding = (WSDualHttpBinding)client.Endpoint.Binding;
String clientcallbackaddress = binding.ClientBaseAddress.AbsoluteUri;
clientcallbackaddress += Guid.NewGuid().ToString();
binding.ClientBaseAddress = new Uri(clientcallbackaddress);
client.Subscribe();
}
public void PostReceived(string postSampleData)
{
MessageBox.Show("PostChange(item {0})", postSampleData);
}
}
and for the code for my data source...
class Program : IPostingContractCallback
{
static void Main(string[] args)
{
InstanceContext site = new InstanceContext(new Program());
PostingContractClient client = new PostingContractClient(site);
client.PublishPost("testing");
Console.WriteLine();
Console.WriteLine("Press ENTER to shut down data source");
Console.ReadLine();
//Closing the client gracefully closes the connection and cleans up resources
client.Close();
}
public void PostReceived(string postSampleData)
{
Console.WriteLine("PostChange(item {0})",postSampleData);
}
}
After running the service, followed by the client, followed by the datasource, I'm suppose to receive a popup messagebox from my client. However there gives an error on the line
PostChangeEvent(this, e);
Object reference not set to an instance of an object.
Anyone know how to solve this?
It sounds like there's nothing subscribed to the event. To check for this, you should use:
var handler = PostChangeEvent;
if (handler != null)
{
handler(this, e);
}
That will stop the NullReferenceException, but of course it won't address why there were no subscribers... you haven't shown anything which subscribes to the event - what were you expecting to be subscribed?