Every Devlopers Nightmare is how well does his/her code fit into the final packaging....
problem with EJB3.x is usage of annotations with out being able to re compile the code with fresh set of args for the unit to pass thru integration test
ex:
#MessageDriven(activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "queue/Messagess") })
Question is How many J2ee Containers guarantee the queue jms box is always "queue/Messagess"
Well the naming can be "queue/xyzabc" .....
How can such arguments be configured in EJB3.x with out recompiling the code ...???
with regards
karthik
Use activation-config-property in XML.
<message-driven>
<ejb-name>YourMDBName</ejb-name>
<activation-config>
<activation-config-property>
<activation-config-property-name>destination</activation-config-property-name>
<activation-config-property-value>YourValue</activation-config-property-value>
</activation-config-property>
</activation-config>
</message-driven>
Just because you use EJB 3.x with annotations for ease-of-development does not mean that using XML to override annotation config data is "wrong".
Related
I am trying to run simple JBoss JMS example, but got this error
Caused by: org.jboss.jca.common.api.validator.ValidateException: IJ010075: The resource adapter metadata must contain either an outbound or inbound configuration
I planned to remove all the classes and add code gradually to see where the problem occurs but even with just this, it doesnt work
package rootPackage;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.TextMessage;
#MessageDriven(name = "MDBService", activationConfig = {
#ActivationConfigProperty(propertyName =
"destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName =
"destination", propertyValue = "java:jboss/jms/queue/ticketQueue"),
#ActivationConfigProperty(propertyName =
"acknowledgeMode", propertyValue = "Auto-acknowledge")})
public class MDBService implements MessageListener {
public void onMessage(Message message) {
TextMessage tm = (TextMessage) message;
try {
System.out.println("Get message " + tm.getText());
} catch (JMSException e) {
System.out.println("Error! " + e);
}
}
}
I use IntelliJ, Java EE6 and JBoss 7.1.1. I added the queue to JNDI via web interface and run JBoss with
-c standalone-full.xml
option.
Here a few points how you could start to find the origin of the issue.
check which resource adapter is configured in your JBoss, either via the admin console http://localhost:9990 or in your standalone-full.xml (subsystem: urn:jboss:domain:resource-adapters)
if a resource adapter is already configured open the ra.xml (inside the resource adapter *.jar, related to the error message it seems there is no section <outbound-resourceadapter> or <inbound-resourceadapter>
You should create WAR or JAR package, not RAR (which is for resource archive).
If you are going to expose some web content (including REST webservices) use WAR package, if you are about to write only business logic use JAR packaging.
If project is under build control tool such as maven just change packaging node value, otherwise change should be made in IDE.
In a CXF SOAP webservice, I'm using the following annotations to disable the xsd validation:
#EndpointProperties({
#EndpointProperty(key = "set-jaxb-validation-event-handler", value = "false")
})
I would like the validation to controlled at runtime (enable/disable it, based on the value of a setting retrieved from a database). My question is: is it possible to disable/enable this handler at runtime? Maybe by writing a custom event handler and not using this property at all?
Thanks.
Edit: an option would be not to disable the validation with set-jaxb-validation-handler, and rather subclass ValidationEventHandler. As explained here, I would then check the database setting in handleEvent and return according to its value.
But there are still a few downsides with this approach: first, this webservice is configured with annotations, and I can't seem to find a way to apply a ValidationEventHandler with annotations (same question as: How to set custom ValidationEventHandler on JAXB unmarshaller when using annotations).
Secondly, it means that the validation will be performed even if I don't need it; I would then lose any performance benefit.
It doesn't in fact exactly suit my needs, so I'm still open to any suggestion.
Yes, it is possible.
MyService service = new MyService();
MyServiceInterface port = service.getMyServicePort();
BindingProvider bindingProvider = (BindingProvider) port;
bindingProvider.getRequestContext().put(
"set-jaxb-validation-event-handler", Boolean.FALSE);
I finally found a working solution.
As I'm running CXF on JBoss EAP 6.0, I added the following configuration to the webservices subsytem in standalone.xml:
<subsystem xmlns="urn:jboss:domain:webservices:1.2">
<!-- ... -->
<endpoint-config name="myconfig">
<property name="set-jaxb-validation-event-handler" value="false"/>
</endpoint-config>
<!-- ...-->
</subsystem>
And the following annotation to the SEI implementation:
#org.jboss.ws.api.annotation.EndpointConfig(configName = "myconfig")
This is the related Maven dependency:
<dependency>
<groupId>org.jboss.ws</groupId>
<artifactId>jbossws-api</artifactId>
<version>1.0.1.Final</version>
<scope>provided</scope>
</dependency>
We still need a restart of the server if we want to change the property value, but it's a lesser evil.
For the people trying to configure that on the bus level, the following worked for me:
<cxf:bus id="soapClientCxfBus" bus="soapClientCxfBus" >
<cxf:properties>
<entry key="set-jaxb-validation-event-handler" value="false" />
</cxf:properties>
</cxf:bus>
I'm trying to create an MDB(EJB 3.0) on WebLogic 10.3.5. to listen to a Queue on an external AMQ server. After much work and combination of tutorials i get the following error when deploying on webLogic.
[EJB:015027]The Message-Driven EJB is transactional but JMS connection factory referenced by the JNDI name: ActiveMQXAConnectionFactory is not a JMS XA connection factory.
Here is a brief of the work i have done:
I have added the corresponding libraries to my WLS classpath (following this tuturial http://amadei.com.br/blog/index.php/connecting-weblogic-and-activemq) and I have created the corresponding JMS Modules as indicated in the tutorial. I have used ActiveMQConnectionFactory initially and ActiveMQXAConnectionFactory later, I also ignore the jms. notation an just put plain names as testQueue.
Then create a simple MDB with the following structure.
I explicitly defined "connectionFactoryJndiName" property because otherwise it assumes a WebLogic connection factory which is not found, and then raises an error.
#MessageDriven(
activationConfig = {
#ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
#ActivationConfigProperty(propertyName = "destination", propertyValue = "testQueue"),
#ActivationConfigProperty(propertyName = "connectionFactoryJndiName", propertyValue = "ActiveMQXAConnectionFactory")
},
mappedName = "testQueue")
public class ROMELReceiver implements MessageListener {
/**
* Default constructor.
*/
public ROMELReceiver() {
// TODO Auto-generated constructor stub
}
/**
* #see MessageListener#onMessage(Message)
*/
public void onMessage(Message message) {
System.out.println("Message received");
}
}
At this point I'm stuck with the error mentioned above. Even though I use ActiveMQXAConnectionFactory instead of simply ActiveMQConnectionFactory, JNDI resources tree in web logic server shows org.apache.activemq.ActiveMQConnectionFactory as class for my configured connection factory.
am i missing something? or is this just a completely wrong way to connect WebLogic whith AMQ?
Thanks in advance.
I know its late but i recently i had to do the same thing and encoutered the same error.
This post helped me:
https://community.oracle.com/thread/3903705
Basically it says to add a new parameter in the jndi properties on the foreign server option on the module in weblogic.
xa=true.
Because activemq is not using Xa connections by default.
How to make maxSession value for an MDB user-configurable?
There is an MDB that listens for a message from a specific queue. It is defined as an annotation.
#ActivationConfigProperty(propertyName = "maxSession", propertyValue = "5").
In order to change the value of the maxSession, the code has to be compiled everytime.
Is there a way to make it user configurable so that there is no build required and without restarting jboss?
Kindly help.
This is the way to externalize this setting from ear:
https://community.jboss.org/thread/178162
But restart is still required.
Update
Found a way to apply new maxSession with system property reference in ejb-jar.xml:
<activation-config-property>
<activation-config-property-name>maxSession</activation-config-property-name>
<activation-config-property-value>${my.mdb.maxSession:30}</activation-config-property-value>
</activation-config-property>
Full JBoss restart is not required, only ear redeploy is needed in this case.
It works for all JBoss versions until JBoss AS 7.
Note that maxSession must be in sync with max pool size:
https://community.jboss.org/message/549083#549083
Note as well, that both the number of sessions and the instance pool size can be specified in an AOP configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<aop xmlns="urn:jboss:aop-beans:1.0">
<domain name="IBMMQ Message Driven Bean" extends="Message Driven Bean" inheritBindings="true">
<annotation expr="class(*)">
#org.jboss.ejb3.annotation.Pool (value="StrictMaxPool", maxSize=10, timeout=10000)
</annotation>
<annotation expr="!class(#org.jboss.ejb3.annotation.DefaultActivationSpecs)">
#org.jboss.ejb3.annotation.DefaultActivationSpecs (value={#javax.ejb.ActivationConfigProperty(propertyName = "channel", propertyValue = "SSL.CLIENTS"), #javax.ejb.ActivationConfigProperty(propertyName = "queueManager", propertyValue = "SSLQM"), #javax.ejb.ActivationConfigProperty(propertyName = "hostName", propertyValue = "10.0.0.124"), #javax.ejb.ActivationConfigProperty(propertyName = "port", propertyValue = "1415"), #javax.ejb.ActivationConfigProperty(propertyName = "transportType", propertyValue = "CLIENT"), #javax.ejb.ActivationConfigProperty(propertyName = "sslCipherSuite", propertyValue = "SSL_RSA_WITH_3DES_EDE_CBC_SHA")})
</annotation>
</domain>
</aop>
You then add the annotation:
#AspectDomain("IBMMQ Message Driven Bean")
to your MDB. This is can be used to externalize both the number of seesions and the instance pool size.
According to this how many Message Driven Beans are created in Jboss? maxSession can't exceed the setting of StrictMaxPool. So when tweaking maxSession - this setting need to be changed as well!
I'm trying to use this method for receiving mail in our EJB3 app. In short, that means creating an MDB with the following annotations:
#MessageDriven(activationConfig = { #ActivationConfigProperty(propertyName = "mailServer", propertyValue = "imap.company.com"),
#ActivationConfigProperty(propertyName = "mailFolder", propertyValue = "INBOX"),
#ActivationConfigProperty(propertyName = "storeProtocol", propertyValue = "imap"),
#ActivationConfigProperty(propertyName = "debug", propertyValue = "false"),
#ActivationConfigProperty(propertyName = "userName", propertyValue = "username"),
#ActivationConfigProperty(propertyName = "password", propertyValue = "pass") })
#ResourceAdapter("mail-ra.rar")
#Name("mailMessageBean")
public class MailMessageBean implements MailListener {
public void onMessage(final Message msg) {
...snip...
}
}
I have this working, but the situation is less than ideal: The hostname, username and password are hardcoded. Short of using ant and build.properties to replace those values before compilation, I don't know how to externalize them.
It would be ideal to use an MBean, but I have no idea how to get the values from the MBean to the MDB configuration.
How should I do this?
You can externalise the annotations into the ejb-jar.xml that you deploy in the META-INF of your jar file as follows:
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar version="3.0">
<enterprise-beans>
<message-driven>
<ejb-name>YourMDB</ejb-name>
<ejb-class>MailMessageBean</ejb-class>
<activation-config>
<activation-config-property>
<activation-config-property-name>username</activation-config-property-name>
<activation-config-property-value>${mdb.user.name}</activation-config-property-value>
</activation-config-property>
...
...
</activation-config>
</message-driven>
</enterprise-beans>
Then you can set the mdb.user.name value as a system property as part of the command line to your application server using -Dmdb.user.name=theUserName and it will magically get picked up by the mdb.
Hope that helps.
As of JBoss AS 5.1 at least, you can use AOP to configure the #ActivationConfigProperties. I discovered this by looking at the examples that jboss provides here. This is useful if you do not want your username and passwords available to the entire container in a systems property, or if you are like me and never, I repeat NEVER, want to deploy an artifact with a username/password in it. Any how, here is the jist...
Annotate the mdb like this...
...
#MessageDriven
#AspectDomain("TestMDBean")
public class TestMDBean implements MessageListener {
...
Then add a ${whatever}-aop.xml to the deploy dir with internals like below. I left the original comments in there in case Jaikiran does make the changes mentioned...
Note: the annotation must be on one
line only.
<?xml version="1.0" encoding="UTF-8"?>
<aop xmlns="urn:jboss:aop-beans:1.0">
<!-- TODO: Jaikiran - These interceptor declarations need not be here since they
are already declared through the ejb3-interceptors-aop.xml. Duplicating them leads to
deployment errors. However, if this custom-ejb3-interceptors-aop.xml needs to be
independent, then we must find a better way of declaring these. Right now, commenting these
out, can be looked at later. -->
<!--
<interceptor class="org.jboss.ejb3.AllowedOperationsInterceptor" scope="PER_VM"/>
<interceptor class="org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.security.RunAsSecurityInterceptorFactory" scope="PER_CLASS"/>
<interceptor class="org.jboss.ejb3.stateless.StatelessInstanceInterceptor" scope="PER_VM"/>
<interceptor factory="org.jboss.ejb3.interceptor.EJB3InterceptorsFactory" scope="PER_CLASS_JOINPOINT"/>
<interceptor factory="org.jboss.aspects.tx.TxInterceptorFactory" scope="PER_CLASS_JOINPOINT"/>
-->
<domain name="TestMDBean" extends="Message Driven Bean" inheritBindings="true">
<annotation expr="!class(#org.jboss.ejb3.annotation.DefaultActivationSpecs)">
#org.jboss.ejb3.annotation.DefaultActivationSpecs (value={#javax.ejb.ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), #javax.ejb.ActivationConfigProperty(propertyName="destination", propertyValue="queue/MyQueue"), #javax.ejb.ActivationConfigProperty(propertyName="user", propertyValue="testusr"), #javax.ejb.ActivationConfigProperty(propertyName="password", propertyValue="testpwd")})
</annotation>
</domain>
</aop>