[ 
https://issues.apache.org/jira/browse/QPID-7747?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15971267#comment-15971267
 ] 

Alex Rudyy edited comment on QPID-7747 at 4/18/17 8:26 AM:
-----------------------------------------------------------

Hi Tomas,

Embedding of Qpid Broker into tests requires more work. Hopefully we can 
improve it in upcoming 7.0 version. Thus, some changes to the code might be 
required on migration to v7.
As Lorenz mentioned in his reply {{broker-core}} does not depend on logback. 
Starting broker using only {{broker-core}} for v6.1 requires some boilerplate 
code.
Let me demonstrate  two approaches you can use:
* Using initial configuration (requires less code and more portable)
* Creation of entire broker programmatically

Here are the maven dependencies you might use in your tests
{code:xml}
<!--- broker dependencies -->
<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-core</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-plugins-memory-store</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
    <version>6.1.2</version>
</dependency>
<!--- client  dependencies -->
<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-jms_1.1_spec</artifactId>
    <version>1.1.1</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-client</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.12</version>
</dependency>
{code}
The above dependencies are for broker and client. Dependency with 
implementations of AMQP protocols 0.8/0.9/0.9.1 is declared in order to use a 
legacy client . You can replace it with AMQP 0.10 protocol or AMQP 1.0 protocol 
modules or use combination of supported protocols.

h5. Using initial configuration 
The following intial configuration can be used in test
{noformat}
{
  "name": "${broker.name}",
  "modelVersion": "6.1",
  "authenticationproviders" : [ {
    "name" : "anonymous",
    "type" : "Anonymous"
  } ],
  "ports" : [  {
    "name" : "AMQP",
    "port" : "${qpid.amqp_port}",
    "authenticationProvider" : "anonymous",
    "virtualhostaliases" : [ {
      "name" : "nameAlias",
      "type" : "nameAlias"
    }, {
      "name" : "defaultAlias",
      "type" : "defaultAlias"
    }, {
      "name" : "hostnameAlias",
      "type" : "hostnameAlias"
    } ]
  }],
  "virtualhostnodes" : [ {
    "name" : "default",
    "type" : "JSON",
    "defaultVirtualHostNode" : "true",
    "virtualHostInitialConfiguration" : "{\"type\": \"Memory\"}",
    "preferenceStoreAttributes": {"type": "Noop"}
  }]
}
{noformat}

The configuration declares AMQP port, anonymous authentication provider and a 
virtual host node of type JSON. You can use Memory Virtual Host Node in the 
tests.

The code below demonstrate how to start broker from initial configuration above:
{code}
private static SystemConfig<?> createSystemConfig(final File workDir)
    {
        TaskExecutor taskExecutor = new TaskExecutorImpl();
        MessageLogger messageLogger = new LoggingMessageLogger();
        EventLogger eventLogger = new EventLogger();
        eventLogger.setMessageLogger(messageLogger);

        PluggableFactoryLoader<SystemConfigFactory>
                configFactoryLoader = new 
PluggableFactoryLoader<>(SystemConfigFactory.class);
        SystemConfigFactory configFactory = 
configFactoryLoader.get(JsonSystemConfigImpl.SYSTEM_CONFIG_TYPE);
        String initialConfigurationUrl = 
InitialConfigurationSystemConfigExample.class.getClassLoader()
                                                                                
      .getResource(
                                                                                
              "test-initial-config.json")
                                                                                
      .toExternalForm();
        Map<String, String> context = new HashMap<>();
        context.put("qpid.work_dir", workDir.getAbsolutePath());
        context.put("qpid.amqp_port", "0");
        context.put("qpid.broker.defaultPreferenceStoreAttributes", "{\"type\": 
\"Noop\"}}");

        Map<String, Object> attributes = new HashMap<>();
        attributes.put("initialConfigurationLocation", initialConfigurationUrl);
        attributes.put("context", context);
        attributes.put("storePath", 
"${json:qpid.work_dir}${file.separator}config.json");
        attributes.put("startupLoggedToSystemOut", "false");


        SystemConfig<?> systemConfig = configFactory.newInstance(taskExecutor, 
eventLogger, new Principal()
        {
            @Override
            public String getName()
            {
                return "system";
            }
        }, attributes);

        systemConfig.open();

        return systemConfig;
    }
{code}

The code above creates a SystemConfig object. It uses given workingDirectory to 
save the configuration created from initial one.
The following snippet demonstrates how you can do messaging
{code}
        File workDir = Files.createTempDir();
        SystemConfig<?> systemConfig = createSystemConfig(workDir);
        try
        {
            JMSClient.sendReceive(port, null, null);
        }
        finally
        {
            systemConfig.close();
            workDir.delete();
        }
{code}

h5. Creation of entire broker programmatically
This approach requires more code. Unfortunately, you cannot start broker from 
zero config. The empty intial configuration is required
The code below demonstrate how you can create, SystemConfig, Port, 
Authentication Provider, User and Virtual Host Node programmatically
{code}
private static SystemConfig createSystemConfig(int port,
                                                   final String userName,
                                                   final String userPassword)
    {
        TaskExecutor taskExecutor = new TaskExecutorImpl();
        MessageLogger messageLogger = new LoggingMessageLogger();
        EventLogger eventLogger = new EventLogger();
        eventLogger.setMessageLogger(messageLogger);

        PluggableFactoryLoader<SystemConfigFactory>
                configFactoryLoader = new 
PluggableFactoryLoader<>(SystemConfigFactory.class);
        SystemConfigFactory configFactory = 
configFactoryLoader.get(MemorySystemConfigImpl.SYSTEM_CONFIG_TYPE);

        taskExecutor.start();
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("initialConfigurationLocation", "data:;base64," + 
DatatypeConverter.printBase64Binary(
                ("{\"name\": \"test\",\"modelVersion\":\"" + 
BrokerModel.MODEL_VERSION + "\"}").getBytes()));
        attributes.put("context", 
Collections.singletonMap("qpid.broker.defaultPreferenceStoreAttributes",
                                                           "{\"type\": 
\"Noop\"}}"));
        SystemConfig systemConfig = configFactory.newInstance(taskExecutor,
                                                              eventLogger,
                                                              new Principal()
                                                              {
                                                                  @Override
                                                                  public String 
getName()
                                                                  {
                                                                      return 
"system";
                                                                  }
                                                              },
                                                              attributes);
        systemConfig.open();

        // get broker
        Broker<?> broker = (Broker<?>) systemConfig.getChild(Broker.class);

        // create Scram SHA256 authentication provider
        Map<String, Object> authenticationProviderAttributes = new HashMap<>();
        authenticationProviderAttributes.put(AuthenticationProvider.TYPE,
                                             
ScramSHA256AuthenticationManager.PROVIDER_TYPE);
        authenticationProviderAttributes.put(AuthenticationProvider.NAME, 
"auth");
        UsernamePasswordAuthenticationProvider
                authenticationManager =
                (UsernamePasswordAuthenticationProvider) 
broker.createChild(AuthenticationProvider.class,
                                                                            
authenticationProviderAttributes);

        // create user
        final Map<String, Object> userAttributes = new HashMap<>();
        userAttributes.put(User.NAME, userName);
        userAttributes.put(User.PASSWORD, userPassword);
        authenticationManager.createChild(User.class, userAttributes);

        // create amqp port
        final Map<String, Object> portAttributes = new HashMap<>();
        portAttributes.put(Port.NAME, "amqp");
        portAttributes.put(Port.PORT, port);
        portAttributes.put(Port.AUTHENTICATION_PROVIDER, 
authenticationManager.getName());
        portAttributes.put(Port.PROTOCOLS, 
Collections.singleton(Protocol.AMQP_0_9_1));
        AmqpPort<?> amqpPort = (AmqpPort<?>) broker.createChild(Port.class, 
portAttributes);


        // create virtual host node and virtual host
        final Map<String, Object> virtualHostNodeAttributes = new HashMap<>();
        virtualHostNodeAttributes.put(VirtualHostNode.NAME, "test");
        virtualHostNodeAttributes.put(VirtualHostNode.TYPE, 
MemoryVirtualHostNode.VIRTUAL_HOST_NODE_TYPE);
        virtualHostNodeAttributes.put("virtualHostInitialConfiguration",
                                      "{\"name\": \"test\",\"modelVersion\":\""
                                      + BrokerModel.MODEL_VERSION
                                      + "\", \"type\": \"Memory\"}");
        
virtualHostNodeAttributes.put(VirtualHostNode.DEFAULT_VIRTUAL_HOST_NODE, true);
        broker.createChild(VirtualHostNode.class, virtualHostNodeAttributes);

        return systemConfig;
    }
{code}

I will attach the source code to the JIRA demonstrating both approaches


was (Author: alex.rufous):
Hi Tomas,

Embedding of Qpid Broker into tests requires more work. Hopefully we can 
improve it in upcoming 7.0 version. Thus, some changes to the code might be 
required on migration to v7.
As Lorenz mentioned in his reply {{broker-core}} does not depend on logback. 
Starting broker using only {{broker-core}} for v6.1 requires some boilerplate 
code.
Let me demonstrate  two approaches you can use:
* Using initial configuration (requires less code and more portable)
* Creation of entire broker programmatically

Here are the maven dependencies you might use in your tests
{code:xml}
<!--- broker dependencies -->
<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-core</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-plugins-memory-store</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-broker-plugins-amqp-0-8-protocol</artifactId>
    <version>6.1.2</version>
</dependency>
<!--- client  dependencies -->
<dependency>
    <groupId>org.apache.geronimo.specs</groupId>
    <artifactId>geronimo-jms_1.1_spec</artifactId>
    <version>1.1.1</version>
</dependency>

<dependency>
    <groupId>org.apache.qpid</groupId>
    <artifactId>qpid-client</artifactId>
    <version>6.1.2</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.12</version>
</dependency>
{code}
The above dependencies are for broker and client. Dependency with 
implementations of AMQP protocols 0.8/0.9/0.9.1 is declared in order to use a 
legacy client . You can replace it with AMQP 0.10 protocol or AMQP 1.0 protocol 
modules or use combination of supported protocols.

h5. Using initial configuration 
The following intial configuration can be used in test
{noformat}
{
  "name": "${broker.name}",
  "modelVersion": "6.1",
  "authenticationproviders" : [ {
    "name" : "anonymous",
    "type" : "Anonymous"
  } ],
  "ports" : [  {
    "name" : "AMQP",
    "port" : "${qpid.amqp_port}",
    "authenticationProvider" : "anonymous",
    "virtualhostaliases" : [ {
      "name" : "nameAlias",
      "type" : "nameAlias"
    }, {
      "name" : "defaultAlias",
      "type" : "defaultAlias"
    }, {
      "name" : "hostnameAlias",
      "type" : "hostnameAlias"
    } ]
  }],
  "virtualhostnodes" : [ {
    "name" : "default",
    "type" : "JSON",
    "defaultVirtualHostNode" : "true",
    "virtualHostInitialConfiguration" : "{\"type\": \"Memory\"}",
    "preferenceStoreAttributes": {"type": "Noop"}
  }]
}
{noformat}

The configuration declares AMQP port, anonymous authentication provider and a 
virtual host node.

The code below demonstrate how to start broker from initial configuration above:
{code}
private static SystemConfig<?> createSystemConfig(final File workDir)
    {
        TaskExecutor taskExecutor = new TaskExecutorImpl();
        MessageLogger messageLogger = new LoggingMessageLogger();
        EventLogger eventLogger = new EventLogger();
        eventLogger.setMessageLogger(messageLogger);

        PluggableFactoryLoader<SystemConfigFactory>
                configFactoryLoader = new 
PluggableFactoryLoader<>(SystemConfigFactory.class);
        SystemConfigFactory configFactory = 
configFactoryLoader.get(JsonSystemConfigImpl.SYSTEM_CONFIG_TYPE);
        String initialConfigurationUrl = 
InitialConfigurationSystemConfigExample.class.getClassLoader()
                                                                                
      .getResource(
                                                                                
              "test-initial-config.json")
                                                                                
      .toExternalForm();
        Map<String, String> context = new HashMap<>();
        context.put("qpid.work_dir", workDir.getAbsolutePath());
        context.put("qpid.amqp_port", "0");
        context.put("qpid.broker.defaultPreferenceStoreAttributes", "{\"type\": 
\"Noop\"}}");

        Map<String, Object> attributes = new HashMap<>();
        attributes.put("initialConfigurationLocation", initialConfigurationUrl);
        attributes.put("context", context);
        attributes.put("storePath", 
"${json:qpid.work_dir}${file.separator}config.json");
        attributes.put("startupLoggedToSystemOut", "false");


        SystemConfig<?> systemConfig = configFactory.newInstance(taskExecutor, 
eventLogger, new Principal()
        {
            @Override
            public String getName()
            {
                return "system";
            }
        }, attributes);

        systemConfig.open();

        return systemConfig;
    }
{code}

The code above creates a SystemConfig object. It uses given workingDirectory to 
save the configuration created from initial one.
The following snippet demonstrates how you can do messaging
{code}
        File workDir = Files.createTempDir();
        SystemConfig<?> systemConfig = createSystemConfig(workDir);
        try
        {
            JMSClient.sendReceive(port, null, null);
        }
        finally
        {
            systemConfig.close();
            workDir.delete();
        }
{code}

h5. Creation of entire broker programmatically
This approach requires more code. Unfortunately, you cannot start broker from 
zero config. The empty intial configuration is required
The code below demonstrate how you can create, SystemConfig, Port, 
Authentication Provider, User and Virtual Host Node programmatically
{code}
private static SystemConfig createSystemConfig(int port,
                                                   final String userName,
                                                   final String userPassword)
    {
        TaskExecutor taskExecutor = new TaskExecutorImpl();
        MessageLogger messageLogger = new LoggingMessageLogger();
        EventLogger eventLogger = new EventLogger();
        eventLogger.setMessageLogger(messageLogger);

        PluggableFactoryLoader<SystemConfigFactory>
                configFactoryLoader = new 
PluggableFactoryLoader<>(SystemConfigFactory.class);
        SystemConfigFactory configFactory = 
configFactoryLoader.get(MemorySystemConfigImpl.SYSTEM_CONFIG_TYPE);

        taskExecutor.start();
        Map<String, Object> attributes = new HashMap<>();
        attributes.put("initialConfigurationLocation", "data:;base64," + 
DatatypeConverter.printBase64Binary(
                ("{\"name\": \"test\",\"modelVersion\":\"" + 
BrokerModel.MODEL_VERSION + "\"}").getBytes()));
        attributes.put("context", 
Collections.singletonMap("qpid.broker.defaultPreferenceStoreAttributes",
                                                           "{\"type\": 
\"Noop\"}}"));
        SystemConfig systemConfig = configFactory.newInstance(taskExecutor,
                                                              eventLogger,
                                                              new Principal()
                                                              {
                                                                  @Override
                                                                  public String 
getName()
                                                                  {
                                                                      return 
"system";
                                                                  }
                                                              },
                                                              attributes);
        systemConfig.open();

        // get broker
        Broker<?> broker = (Broker<?>) systemConfig.getChild(Broker.class);

        // create Scram SHA256 authentication provider
        Map<String, Object> authenticationProviderAttributes = new HashMap<>();
        authenticationProviderAttributes.put(AuthenticationProvider.TYPE,
                                             
ScramSHA256AuthenticationManager.PROVIDER_TYPE);
        authenticationProviderAttributes.put(AuthenticationProvider.NAME, 
"auth");
        UsernamePasswordAuthenticationProvider
                authenticationManager =
                (UsernamePasswordAuthenticationProvider) 
broker.createChild(AuthenticationProvider.class,
                                                                            
authenticationProviderAttributes);

        // create user
        final Map<String, Object> userAttributes = new HashMap<>();
        userAttributes.put(User.NAME, userName);
        userAttributes.put(User.PASSWORD, userPassword);
        authenticationManager.createChild(User.class, userAttributes);

        // create amqp port
        final Map<String, Object> portAttributes = new HashMap<>();
        portAttributes.put(Port.NAME, "amqp");
        portAttributes.put(Port.PORT, port);
        portAttributes.put(Port.AUTHENTICATION_PROVIDER, 
authenticationManager.getName());
        portAttributes.put(Port.PROTOCOLS, 
Collections.singleton(Protocol.AMQP_0_9_1));
        AmqpPort<?> amqpPort = (AmqpPort<?>) broker.createChild(Port.class, 
portAttributes);


        // create virtual host node and virtual host
        final Map<String, Object> virtualHostNodeAttributes = new HashMap<>();
        virtualHostNodeAttributes.put(VirtualHostNode.NAME, "test");
        virtualHostNodeAttributes.put(VirtualHostNode.TYPE, 
MemoryVirtualHostNode.VIRTUAL_HOST_NODE_TYPE);
        virtualHostNodeAttributes.put("virtualHostInitialConfiguration",
                                      "{\"name\": \"test\",\"modelVersion\":\""
                                      + BrokerModel.MODEL_VERSION
                                      + "\", \"type\": \"Memory\"}");
        
virtualHostNodeAttributes.put(VirtualHostNode.DEFAULT_VIRTUAL_HOST_NODE, true);
        broker.createChild(VirtualHostNode.class, virtualHostNodeAttributes);

        return systemConfig;
    }
{code}

I will attach the source code to the JIRA demonstrating both approaches

> Logging: Depend only on slf4j and remove logback dependencies
> -------------------------------------------------------------
>
>                 Key: QPID-7747
>                 URL: https://issues.apache.org/jira/browse/QPID-7747
>             Project: Qpid
>          Issue Type: Improvement
>            Reporter: Tomas Klimavicius
>         Attachments: embedded-broker-example.tar.gz
>
>
> Qpid is depending on logback as it's log implementation, but this makes it 
> horrible to use inside projects that already use log4j or slf4j-jdk14.
> It would be much easier for users if the source code would only depened on 
> slf4j. Now if we exclude logback and expect qpid to use our provided logger 
> the code does not compile since qpid actually depends on logback - 
> ch.qos.logback.classic.Logger logger = 
> (ch.qos.logback.classic.Logger)LoggerFactory.getLogger("ROOT");
> And if you use something else you get a class cast exception. 
> Also slf4j complains on every startup when you have multiple implementations 
> in your classpath



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to