0

I'm currently working on a JMS project and I have created 2 keys and 2 certificates as well as a TrustStorage, mytruststore which I created through Qpid's UI. In my jndi.properties file I have the following code:

//Set the InitialContextFactory class to use

java.naming.factory.initial = org.apache.qpid.jms.jndi.JmsInitialContextFactory

//Define the required ConnectionFactory instances
//connectionfactory.<JNDI-lookup-name> = <URI>

connectionfactory.myFactoryLookup = amqp://localhost:5672
connectionfactory.producerConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
connectionfactory.consumer1ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
connectionfactory.consumer2ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''

//Configure the necessary Queue and Topic objects
//queue.<JNDI-lookup-name> = <queue-name>
//topic.<JNDI-lookup-name> = <topic-name>

queue.myQueueLookup = queue
topic.myTopicLookup = topic
queue.myTestQueue = queue

In my EncryptionExample.java class I have the following code:

package org.apache.qpid.jms.example;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
public class EncryptionExample {
    public EncryptionExample() {
    }

    public static void main(String[] args) throws Exception {
        EncryptionExample encryptionExampleApp = new EncryptionExample();
        encryptionExampleApp.runProducerExample();
        encryptionExampleApp.runReceiverExample();
    }

    private void runProducerExample() throws Exception
    {
        Connection connection = createConnection("producerConnectionFactory");
        try {
            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
            Destination destination = createDesination("myTestQueue");

            MessageProducer messageProducer = session.createProducer(destination);
            TextMessage message = session.createTextMessage("Hello world!");

            // ============== Enable encryption for this message ==============
            message.setBooleanProperty("x-qpid-encrypt", true);
            // ============== Configure recipients for encryption ==============
            message.setStringProperty("x-qpid-encrypt-recipients", "CN=client1, OU=Qpid, O=Apache, C=US");

            messageProducer.send(message);
            session.commit();
        }
        finally {
            connection.close();
        }
    }

    private void runReceiverExample() throws Exception
    {
        Connection connection = createConnection("consumer1ConnectionFactory");
        try {
            connection.start();
            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
            Destination destination = createDesination("myTestQueue");
            MessageConsumer messageConsumer = session.createConsumer(destination);
            Message message = messageConsumer.receive();
            if (message instanceof TextMessage) {
                // application logic
                System.out.println(((TextMessage) message).getText());
            } else if (message instanceof BytesMessage) {
                // handle potential decryption failure
                System.out.println("Potential decryption problem. Application not in list of intended recipients?");
            }
            session.commit();
        }
        finally {
            connection.close();
        }
    }

    ///////////////////////////////////////
    // The following is boilerplate code //
    ///////////////////////////////////////

    private Connection createConnection(final String connectionFactoryName) throws JMSException, IOException, NamingException
    {
        try (InputStream resourceAsStream = getResourceAsStream("jndi.properties")) {
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            Context context = new InitialContext(properties);
            ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(connectionFactoryName);
            final Connection connection = connectionFactory.createConnection();
            context.close();
            return connection;
        }
    }

    private InputStream getResourceAsStream(String string) {
        // TODO Auto-generated method stub
        return null;
    }

    private Destination createDesination(String desinationJndiName) throws IOException, NamingException
    {
        try (InputStream resourceAsStream = this.getClass().getResourceAsStream("example.properties")) {
            Properties properties = new Properties();
            properties.load(resourceAsStream);
            Context context = new InitialContext(properties);
            Destination destination = (Destination) context.lookup(desinationJndiName);
            context.close();
            return destination;
        }
    }
}

When I'm trying to build it I get the following exceptions.

Exception in thread "main" java.lang.NullPointerException

at java.util.Properties$LineReader.readLine(Unknown Source)

at java.util.Properties.load0(Unknown Source)

at java.util.Properties.load(Unknown Source)

at org.apache.qpid.jms.example.EncryptionExample.createConnection(EncryptionExample.java:106)

at org.apache.qpid.jms.example.EncryptionExample.runProducerExample(EncryptionExample.java:54)

at org.apache.qpid.jms.example.EncryptionExample.main(EncryptionExample.java:48)

I assume that something's wrong with the following code in jndi.properties file:

    connectionfactory.myFactoryLookup = amqp://localhost:5672
    connectionfactory.producerConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/mytruststore''
    connectionfactory.consumer1ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''
    connectionfactory.consumer2ConnectionFactory = amqp://admin:admin@?brokerlist='tcp://localhost:5672?encryption_key_store='C:\OpenSSL-Win64\bin\mytruststorage.jks'&encryption_key_store_password='thanos''

This is my solution Explorer:

enter image description here

HelloIT
  • 172
  • 2
  • 22
  • Where is `jndi.properties` located? – Jeremy Mar 05 '17 at 16:02
  • I have edited the post by adding a picture of my solution's explorer. – HelloIT Mar 05 '17 at 16:03
  • The NullPointerException is coming from your own code. You have a method getResourceAsStream which is unimplemented and returns null. You probably mean to call https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getResourceAsStream-java.lang.String- – k-wall Mar 06 '17 at 10:17
  • I also note you are trying to use the Qpid JMS Client (https://qpid.apache.org/components/jms/index.html) with the message encryption feature. This won't work. We have not yet decided how encrypted messages will be represented in AMQP 1.0 and the Qpid JMS Client (which uses AMQP 1.0) does not provide the support. The older Qpid JMS for AMQP 0-8..0-10 (https://qpid.apache.org/components/jms/amqp-0-x.html) does support the feature in a Qpid vendor specific way. If you are using Maven you need to switch from using artefact qpid-jms-client to quid-client if you want to use this feature. – k-wall Mar 06 '17 at 10:25

2 Answers2

1

This first and biggest problem you have is that you are trying to use connection URIs and client features from a client other than the one you have configured you project to use. You seem to be using Qpid JMS which is the new AMQP 1.0 client developed at the Qpid project. This client uses a different URI syntax that the previous AMQP 0.x clients and you will get exception from the connection factory when passing in these invalid URIs.

The other problem you will have (which was called out in the comments on your post) is that there is not message encryption feature in the AMQP 1.0 JMS client so that would be your next problem once you got the URIs correctly defined.

The documentation for the newer AMQP 1.0 JMS client is here.

Tim Bish
  • 17,475
  • 4
  • 32
  • 42
  • I would like to ask something more. Is there any way to system.out.println(`themessagebody`)? – HelloIT Mar 06 '17 at 18:30
  • sure, get the message body from the incoming message and print it. – Tim Bish Mar 06 '17 at 19:06
  • Perfect I found the `getText()` function. Unfortunately I'm totally new to Qpid and I might have more questions. I will be commenting here if I come up with something newer. I deeply appreciate your help! – HelloIT Mar 07 '17 at 12:19
  • 1
    If this question has been answered then please mark it as resolved and ask new one's as they arise, that's how SO works. – Tim Bish Mar 07 '17 at 16:30
  • Have a look to my following [post](http://stackoverflow.com/questions/42655951/json-returned-by-solr) – HelloIT Mar 07 '17 at 18:54
0

You cannot use // for comments in Properties files. Use # or ! instead.

See: https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#load-java.io.Reader-

Jeremy
  • 22,188
  • 4
  • 68
  • 81
  • That's the code I simply pasted from the [docs](https://qpid.apache.org/releases/qpid-java-6.1.1/jms-client-0-8/book/JMS-Client-Message-Encryption-Example.html) but in stackoverflow it interprets `#` as bold, that's why I changed them. – HelloIT Mar 05 '17 at 16:06