[
https://issues.apache.org/jira/browse/QPID-7747?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15971267#comment-15971267
]
Alex Rudyy commented on QPID-7747:
----------------------------------
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 potable)
* 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 . AMQP 1.0 protocol is not fully finished in 6.1 Broker. In order
to use AMQP 1.0 you need to migrate to upcoming Qpid Broker v7
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
>
> 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]