Я хочу активировать пользовательский прослушиватель сообщений на сервере приложений Liberty.
это мой код:
@MessageDriven(name = "Receiver")
public class Receiver implements InboundListener {
@Override
public void receiveMessage(String message) {
System.out.println("Message Received : " + message);
}
}
и это server.xml:
<?xml version="1.0" encoding="UTF-8"?>
<server description="Dandelion IOT server">
<featureManager>
<feature>cdi-2.0</feature>
<feature>beanValidation-2.0</feature>
<feature>appSecurity-3.0</feature>
<feature>jpa-2.2</feature>
<feature>jaxrs-2.1</feature>
<feature>jsonb-1.0</feature>
<feature>jsonp-1.1</feature>
<feature>managedBeans-1.0</feature>
<feature>websocket-1.1</feature>
<feature>ejbLite-3.2</feature>
<feature>jca-1.7</feature>
<feature>jndi-1.0</feature>
<feature>mdb-3.2</feature>
<feature>localConnector-1.0</feature>
</featureManager>
<library id="DandelionLibs">
<fileset dir="/etc/dandelion/lib" includes="*.jar"/>
</library>
<jdbcDriver id="database-driver" libraryRef="DandelionLibs"/>
<dataSource jndiName="JTA-DataSource" transactional="true" jdbcDriverRef="database-driver">
<properties databaseName="${database.name}" serverName="${database.hostname}" portNumber="${database.port}"
user="${database.username}" password="${database.password}"/>
</dataSource>
<resourceAdapter id="dra" autoStart="true" location="/etc/dandelion/lib/RA.rar"/>
<connectionFactory jndiName="h5/sampleConnection">
<properties.dra/>
</connectionFactory>
<activationSpec id="h5/inboundListener">
<properties.dra.DandelionActivationSpec/>
</activationSpec>
<webApplication id="dandelion-web"
location="dandelion-war-0.1-SNAPSHOT.war"
name="dandelion-web">
<classloader classProviderRef="dra"/>
</webApplication>
<basicRegistry id="basic" realm="BasicRealm"/>
<httpSession securityIntegrationEnabled="false"/>
<httpEndpoint id="defaultHttpEndpoint" httpPort="8080" httpsPort="9443">
<httpOptions http2="enabled"/>
</httpEndpoint>
<webContainer disableXPoweredBy="true"/>
<applicationManager autoExpand="true"/>
<applicationMonitor updateTrigger="mbean"/>
</server>
и моя спецификация активации:
@Activation(messageListeners = InboundListener.class)
public class DandelionActivationSpec implements ActivationSpec {
private ResourceAdapter resourceAdapter;
@Override
public void validate() throws InvalidPropertyException {
}
@Override
public ResourceAdapter getResourceAdapter() {
return resourceAdapter;
}
@Override
public void setResourceAdapter(ResourceAdapter ra) throws ResourceException {
this.resourceAdapter = ra;
}
}
и ra.xml:
<?xml version="1.0" encoding="UTF-8"?>
<connector 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/connector_1_7.xsd"
version="1.7">
<description>Sample Resource Adapter</description>
<display-name>Sample Resource Adapter</display-name>
<eis-type>Sample Resource Adapter</eis-type>
<resourceadapter-version>1.0</resourceadapter-version>
<license>
<license-required>false</license-required>
</license>
<resourceadapter>
<resourceadapter-class>org.company.dandelion.adapter.DandelionResourceAdapter</resourceadapter-class>
<outbound-resourceadapter>
<connection-definition>
<managedconnectionfactory-class>org.company.dandelion.adapter.DandelionManagedConnectionFactory</managedconnectionfactory-class>
<connectionfactory-interface>org.company.dandelion.api.DandelionConnectionFactory</connectionfactory-interface>
<connectionfactory-impl-class>org.company.dandelion.adapter.DandelionConnectionFactoryImpl</connectionfactory-impl-class>
<connection-interface>org.company.dandelion.api.DandelionConnection</connection-interface>
<connection-impl-class>org.company.dandelion.adapter.DandelionConnectionImpl</connection-impl-class>
</connection-definition>
<transaction-support>NoTransaction</transaction-support>
<reauthentication-support>false</reauthentication-support>
</outbound-resourceadapter>
<inbound-resourceadapter>
<messageadapter>
<messagelistener>
<messagelistener-type>org.company.dandelion.api.InboundListener</messagelistener-type>
<activationspec>
<activationspec-class>org.company.dandelion.adapter.DandelionActivationSpec</activationspec-class>
</activationspec>
</messagelistener>
</messageadapter>
</inbound-resourceadapter>
</resourceadapter>
</connector>
Сервер приложений Liberty приводит к этому журналу на консоли:
[WARNING ] CNTR4015W: The message endpoint for the Receiver message-driven bean cannot be activated because the dandelion-war-0.1-SNAPSHOT/Receiver activation specification is not available. The message endpoint will not receive messages until the activation specification becomes available.
Адаптер исходящих ресурсов работает без проблем, но входящие не получают никаких сообщений!
Я прочитал эти ссылки, прежде чем задавать этот вопрос, но не могу понять, как можно решить эту проблему:
Ссылка 1
Ссылка 2
Ссылка 3
В какой части конфигурации/кода возникла проблема?
ОБНОВЛЕНИЕ:
я меняю конфигурацию на это:
<activationSpec id="dandelion-web/Receiver">
<properties.dra/>
</activationSpec>
<webApplication id="dandelion-web"
location="dandelion-web.war"
name="dandelion-web">
<classloader classProviderRef="dra"/>
</webApplication>
теперь получите эту ошибку на консоли:
[AUDIT ] J2CA7001I: Resource adapter dra installed in 1.911 seconds.
[AUDIT ] CWWKT0016I: Web application available (default_host): http://localhost:8080/
[AUDIT ] CWWKZ0001I: Application dandelion started in 8.064 seconds.
[err] javax.resource.spi.UnavailableException: activating thread not allowed to create endpoint during activation.
[err] at com.ibm.ws.ejbcontainer.mdb.BaseMessageEndpointFactory.createEndpoint(BaseMessageEndpointFactory.java:406)
[err] at [internal classes]
[err] at com.company.dandelion.adapter.DandelionResourceAdapter.endpointActivation(DandelionResourceAdapter.java:56)
[err] at com.ibm.ws.jca.service.EndpointActivationService.activateEndpoint(EndpointActivationService.java:585)
[err] at [internal classes]
[err] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[err] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
[err] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[err] at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[err] at org.apache.felix.scr.impl.inject.methods.BaseMethod.invokeMethod(BaseMethod.java:242)
[err] at org.apache.felix.scr.impl.inject.methods.BaseMethod.access$500(BaseMethod.java:41)
[err] at org.apache.felix.scr.impl.inject.methods.BaseMethod$Resolved.invoke(BaseMethod.java:678)
[err] at [internal classes]
[err] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[err] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[err] at java.base/java.lang.Thread.run(Thread.java:834)
[AUDIT ] CWWKF0012I: The server installed the following features: [appSecurity-3.0, beanValidation-2.0, cdi-2.0, distributedMap-1.0, ejbLite-3.2, el-3.0, jaxrs-2.1, jaxrsClient-2.1, jca-1.7, jdbc-4.2, jndi-1.0, jpa-2.2, jpaContainer-2.2, jsonb-1.0, jsonp-1.1, localConnector-1.0, managedBeans-1.0, mdb-3.2, servlet-4.0, ssl-1.0, websocket-1.1].
[AUDIT ] CWWKF0011I: The dandelion server is ready to run a smarter planet. The dandelion server started in 12.919 seconds.
это мой DandelionResourceAdapter:
@Connector(
description = "Sample Resource Adapter",
displayName = "Sample Resource Adapter",
eisType = "Sample Resource Adapter",
version = "1.0"
)
public class DandelionResourceAdapter implements ResourceAdapter {
final Map<DandelionActivationSpec, EndpointTarget> targets = new ConcurrentHashMap<>();
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException {
}
public void stop() {
}
public void endpointActivation(final MessageEndpointFactory messageEndpointFactory,
final ActivationSpec activationSpec) {
final DandelionActivationSpec sampleActivationSpec = (DandelionActivationSpec) activationSpec;
// ->>>>>>>>> EXCEPTION FOR THIS LINES :
try {
final MessageEndpoint messageEndpoint = messageEndpointFactory.createEndpoint(null);
final EndpointTarget target = new EndpointTarget(messageEndpoint);
targets.put(sampleActivationSpec, target);
} catch (Exception e) {
e.printStackTrace();
}
}
public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) {
final DandelionActivationSpec sampleActivationSpec = (DandelionActivationSpec) activationSpec;
final EndpointTarget endpointTarget = targets.get(sampleActivationSpec);
if (endpointTarget == null) {
throw new IllegalStateException("No EndpointTarget to undeploy for ActivationSpec " + activationSpec);
}
endpointTarget.messageEndpoint.release();
}
public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException {
return new XAResource[0];
}
public void sendMessage(final String message) {
final Collection<EndpointTarget> endpoints = this.targets.values();
for (final EndpointTarget endpoint : endpoints) {
endpoint.invoke(message);
}
}
public static class EndpointTarget {
private final MessageEndpoint messageEndpoint;
public EndpointTarget(final MessageEndpoint messageEndpoint) {
this.messageEndpoint = messageEndpoint;
}
public void invoke(final String message) {
((InboundListener) this.messageEndpoint).receiveMessage(message);
}
}
}