I am trying to stop a MDB in JBoss 5.1.0.
My code is as follows :
public static void stopAllMDB()
throws InterruptedException, MalformedObjectNameException, NullPointerException {
String currentVersion = "1.0";
for (String name : Util.MDB_NAMES) {
String mbean = "jboss.j2ee:ear=myEar" + currentVersion + ".ear,jar=myJar.jar,name=myMDB,service=EJB3";
ObjectName objName = new ObjectName(mbean);
System.out.println("Stop MDB " + name);
try {
MBeanServer mbeanServer = MBeanServerLocator.locateJBoss();
MessagingDelegateWrapperMBean invoker = (MessagingDelegateWrapperMBean)MBeanProxy.get(MessagingDelegateWrapperMBean.class,
objName, mbeanServer);
invoker.stopDelivery();
}
} catch (Exception e) {
}
}
But if fails at
MessagingDelegateWrapperMBean invoker = (MessagingDelegateWrapperMBean)MBeanProxy.get(MessagingDelegateWrapperMBean.class,objName, mbeanServer)
with
Illegal argument exception.
Apparently the code I was using wasn't working. Don't know why. On a JBoss 5.1.0 GA platform the following apply :
MBeanServer mbeanServer = MBeanServerLocator.locateJBoss();
String mbean = "jboss.j2ee:ear=myEar.ear,jar=all-ejbs.jar,name=" + name + ",service=EJB3";
ObjectName objectName = new ObjectName(mbean);
mbeanServer.invoke(objectName, "stopDelivery", new Object[] {}, null);
And as a remark I didn't experience the session exception you got.
Related
I use a protocol mapper to enrich the token with data from a custom database. How should I deploy the driver to use in the protocol mapper? If II copy the driver in /standalone/lib/ext keycloak folder the when the mapper is executing I get the error
SQL exception occuredjava.sql.SQLException: No suitable driver found for jdbc:oracle:thin:#.......:1521/CASDB
where should the driver be placed? Is it really necessary to deploy the driver as keycloak module?
my protocol mapper code
#Override
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession, KeycloakSession keycloakSession, ClientSessionContext clientSessionCtx) {
String field = mappingModel.getConfig().get(FIELD_NAME);
String type = mappingModel.getConfig().get(TYPE);
String value = "Test " + type;
System.out.println(">>>>>>>>>>>> " + type);
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection con = DriverManager.getConnection(
"jdbc:oracle:thin:#....:1521/CASDB",
"....",
"....");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM CUSTOMER where CUSTOMER_ID = .....");
rs.close();
stmt.close();
con.close();
} catch (SQLException e) {
System.out.println("SQL exception occured" + e);
} finally {
}
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, value);
}
the error is
12:54:40,579 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-6) Uncaught server error: java.lang.NoClassDefFoundError: oracle/jdbc/driver/OracleDriver
at com.betex.keycloak.mapper.UserAttributeMapper.setClaim(UserAttributeMapper.java:72)
at org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformUserInfoToken(AbstractOIDCProtocolMapper.java:71)
at org.keycloak.protocol.oidc.TokenManager.lambda$transformUserInfoAccessToken$8(TokenManager.java:716)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at java.util.stream.SortedOps$RefSortingSink.end(SortedOps.java:390)
at java.util.stream.Sink$ChainedReference.end(Sink.java:258)
at java.util.stream.Sink$C
But if test the connection via wildfly datasource it works ok
I found the solution creating a XADatasource on wildfly server and obtaining it via JNDI inside the code of protocol mapper. Where the DatasourceName is the name defined in your wildfly datasource config
Sample code :
InitialContext initialContext = new InitialContext();
Context context = (Context) initialContext.lookup("java:jboss");
DataSource DATASOURCE = (DataSource) context.lookup("/datasources/DatasourceName");
We work with a Websphere cluster with two apps in it (app1 and app2). I can call EJBs from both apps from my local spring boot out of Intellij-Idea.
When I deploy the spring boot application to the companies private openshift cloud then there is a marshalling exception in one of the two services (client side) talking to one of the websphere apps.
#Service
public class App1BookingsManagementService implements EjbService<DomainFacade> {
private static final String DOMAINFACADE_EJB_NAME = "ejb/org/company/app/DomainFacade";
private static final Logger LOG = LoggerFactory.getLogger(App1BookingsManagementService.class);
#Autowired
private InitialContext initialContext;
public List<BookingDataRow> getBookingsToday() {
DomainFacade domainFacade = null;
try {
domainFacade = createEjbStub();
BookingSelektionskriterien selektionskriterien = new BookingSelektionskriterien();
selektionskriterien.setTerminFrom(valueOf(now()));
selektionskriterien.setTerminUntil(valueOf(now().plusDays(1)));
ResultList<BookingDataRow> resultList = domainFacade.sucheBookingsDataRows(selektionskriterien);
if (resultList == null) {
LOG.warn("Error in EJB {} from APP1 returned null. ", DOMAINFACADE_EJB_NAME);
}
LOG.info("Calling EJB sucheBookingsDataRows returned {} results. ", resultList.getList().size());
return resultList.getList();
} catch (NamingException | CreateException | RemoteException | DomainException e) {
LOG.error("Error in calling EJB {} from APP1: {}, {}", DOMAINFACADE_EJB_NAME, e.getClass().getName(), e.getMessage());
} finally {
if (domainFacade != null) {
try {
domainFacade.remove();
} catch (RemoteException | RemoveException e) {
LOG.error("could not remove ejb {}", DOMAINFACADE_EJB_NAME, e);
}
}
}
return Collections.emptyList();
}
public DomainFacade createEjbStub() throws NamingException, RemoteException, CreateException {
Object stub = initialContext.lookup(DOMAINFACADE_EJB_NAME);
DomainFacadeHome facadeHome = (DomainFacadeHome) PortableRemoteObject.narrow(stub, DomainFacadeHome.class);
return facadeHome.create();
}
}
Here the config:
#Configuration
public class CorbaConfig {
#Value("${corba-location}")
private String corbaLocation;
#Value("classpath:sas.client.props")
private Resource sasClientProps;
#Bean
public InitialContext corbaContext() throws NamingException, IOException {
Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory");
env.put(PROPS.HOSTNAME_NORMALIZER, PROPS.HOSTNAME_NORMALIZER_NONE);
env.put("com.ibm.CORBA.ConfigURL", sasClientProps.getInputStream());
env.put(Context.PROVIDER_URL, corbaLocation);
return new InitialContext(env);
}
#Bean
public MBeanServer mbeanServer() {
MBeanServerFactoryBean factory = new MBeanServerFactoryBean();
factory.setLocateExistingServerIfPossible(true);
factory.afterPropertiesSet();
return factory.getObject();
}
}
This is the error I see in openshift:
2021-02-04 08:14:53,714 [ERROR] P=891120:O=0:CT appname=app-ejbcall corid= c.s.n.e.s.App1BookingsManagementService: Error in calling EJB ejb/org/company/app/DomainFacade from APP1: java.rmi.MarshalException, CORBA MARSHAL 0x4942f89a No; nested exception is:
org.omg.CORBA.MARSHAL:
>> SERVER (id=431c9d95, host=was.company.org) TRACE START:
>> org.omg.CORBA.MARSHAL: Unable to read value from underlying bridge : Default data must be read first vmcid: IBM minor code: 89A completed: No
>> at com.ibm.rmi.iiop.CDRReader.read_value(CDRReader.java:1644)
>> at com.ibm.rmi.iiop.EncoderInputStream.read_value(EncoderInputStream.java:970)
>> at org.company.app.Domain.ejb.facade._EJSRemoteStatelessDomainFacade_a1729579_Tie.sucheBookingenDataRows(Unknown Source)
>> at org.company.app.Domain.ejb.facade._EJSRemoteStatelessDomainFacade_a1729579_Tie._invoke(Unknown Source)
>> at com.ibm.CORBA.iiop.ServerDelegate.dispatchInvokeHandler(ServerDelegate.java:638)
>> at com.ibm.CORBA.iiop.ServerDelegate.dispatch(ServerDelegate.java:508)
>> at com.ibm.rmi.iiop.ORB.process(ORB.java:613)
>> at com.ibm.CORBA.iiop.ORB.process(ORB.java:1584)
>> at com.ibm.rmi.iiop.Connection.doRequestWork(Connection.java:3190)
>> at com.ibm.rmi.iiop.Connection.doWork(Connection.java:3051)
>> at com.ibm.rmi.iiop.WorkUnitImpl.doWork(WorkUnitImpl.java:64)
>> at com.ibm.ws.giop.threadpool.WorkQueueElement.dispatch(WorkQueueElement.java:174)
>> at com.ibm.ws.giop.filter.GiopFilterChain.processMessage(GiopFilterChain.java:203)
>> at com.ibm.ws.giop.threadpool.PooledThread.handleRequest(PooledThread.java:81)
>> at com.ibm.ws.giop.threadpool.PooledThread.run(PooledThread.java:102)
>> at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1892)
>> SERVER (id=431c9d95, host=was.company.org) TRACE END.
vmcid: IBM minor code: 89A completed: No
Locally there is no problem talking to the same websphere server. One guess was the RMI stub is not the same but then it would be also a problem locally, no?
App 1
App 2
Local Spring Boot run in IDE
OK
OK
Deployt in Openshift Cloud
OK
NOK
The problem was that I configured the build with jdk-8 but at runtime the jre was set to version 11.
So I had to find the internal configuration for the correct docker file to use java 8.
I have a Project with Spring AMQP (1.7.12.RELEASE).
If I put a value for the correlationId field (etMessageProperties (). SetCorrelationId) and I use GZipPostProcessor, the following error always occurs:
"org.springframework.amqp.AmqpUnsupportedEncodingException: java.io.UnsupportedEncodingException: gzip"
To solve it, it seems that it works using the following code:
DefaultMessagePropertiesConverter messageConverter = new DefaultMessagePropertiesConverter();
messageConverter.setCorrelationIdAsString(DefaultMessagePropertiesConverter.CorrelationIdPolicy.STRING);
template.setMessagePropertiesConverter(messageConverter);
but I do not know what implications it will have to use it in real with clients that do not use Spring AMQP (I establish this field if the message that has reached me has it).
I enclose a complete example of code:
#Configuration
public class SimpleProducerGZIP
{
static final String queueName = "spring-boot";
#Bean
public CachingConnectionFactory connectionFactory() {
com.rabbitmq.client.ConnectionFactory factory = new com.rabbitmq.client.ConnectionFactory();
factory.setHost("localhost");
factory.setAutomaticRecoveryEnabled(false);
CachingConnectionFactory connectionFactory = new CachingConnectionFactory(factory);
return connectionFactory;
}
#Bean
public AmqpAdmin amqpAdmin() {
RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory());
rabbitAdmin.setAutoStartup(true);
return rabbitAdmin ;
}
#Bean
Queue queue() {
Queue qr = new Queue(queueName, false);
qr.setAdminsThatShouldDeclare(amqpAdmin());
return qr;
}
#Bean
public RabbitTemplate rabbitTemplate()
{
RabbitTemplate template = new RabbitTemplate(connectionFactory());
template.setEncoding("gzip");
template.setBeforePublishPostProcessors(new GZipPostProcessor());
// TODO :
DefaultMessagePropertiesConverter messageConverter = new DefaultMessagePropertiesConverter();
messageConverter.setCorrelationIdAsString(DefaultMessagePropertiesConverter.CorrelationIdPolicy.STRING);
template.setMessagePropertiesConverter(messageConverter);
return template;
}
public static void main(String[] args)
{
#SuppressWarnings("resource")
ApplicationContext context = new AnnotationConfigApplicationContext(SimpleProducerGZIP.class);
RabbitTemplate _rabbitTemplate = context.getBean(RabbitTemplate.class);
int contador = 0;
try {
while(true)
{
contador = contador + 1;
int _nContador = contador;
System.out.println("\nInicio envio : " + _nContador);
Object _o = new String(("New Message : " + contador));
try
{
_rabbitTemplate.convertAndSend(queueName, _o,
new MessagePostProcessor() {
#SuppressWarnings("deprecation")
#Override
public Message postProcessMessage(Message msg) throws AmqpException {
if(_nContador%2 == 0) {
System.out.println("\t--- msg.getMessageProperties().setCorrelationId ");
msg.getMessageProperties().setCorrelationId("NewCorrelation".getBytes(StandardCharsets.UTF_8));
}
return msg;
}
}
);
System.out.println("\tOK");
}catch (Exception e) {
System.err.println("\t\tError en envio : " + contador + " - " + e.getMessage());
}
System.out.println("Fin envio : " + contador);
Thread.sleep(500);
}
}catch (Exception e) {
System.err.println("Exception : " + e.getMessage());
}
}
}
The question is, if I change the configuration of the rabbitTemplate so that the error does not happen, can it have implications for clients that use Spring AMQP or other alternatives?
--- EDIT (28/03/2019)
This is the complete stack trace with the code:
org.springframework.amqp.AmqpUnsupportedEncodingException: java.io.UnsupportedEncodingException: gzip
at org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter.fromMessageProperties(DefaultMessagePropertiesConverter.java:211)
at org.springframework.amqp.rabbit.core.RabbitTemplate.doSend(RabbitTemplate.java:1531)
at org.springframework.amqp.rabbit.core.RabbitTemplate$3.doInRabbit(RabbitTemplate.java:716)
at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1455)
at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1411)
at org.springframework.amqp.rabbit.core.RabbitTemplate.send(RabbitTemplate.java:712)
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertAndSend(RabbitTemplate.java:813)
at org.springframework.amqp.rabbit.core.RabbitTemplate.convertAndSend(RabbitTemplate.java:791)
at es.jab.example.SimpleProducerGZIP.main(SimpleProducerGZIP.java:79)
Caused by: java.io.UnsupportedEncodingException: gzip
at java.lang.StringCoding.decode(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at java.lang.String.<init>(Unknown Source)
at org.springframework.amqp.rabbit.support.DefaultMessagePropertiesConverter.fromMessageProperties(DefaultMessagePropertiesConverter.java:208)
... 8 more
I'd be interested to see the complete stack trace for more information about the problem.
This code was part of a transition from a byte[] correlation Id to a String. This was needed to avoid a byte[]/String/byte[] conversion.
When the policy is String, you should use the correlationIdString property instead of correlationId. Otherwise, the correlationId won't be mapped in outbound messages (we don't look at correlationId in that case). For inbound messages it controls which property is populated.
In 2.0 and later, correlationId is now a String instead of a byte[] so this setting is no longer needed.
EDIT
Now I see the stack trace, this...
template.setEncoding("gzip");
...is wrong.
/**
* The encoding to use when inter-converting between byte arrays and Strings in message properties.
*
* #param encoding the encoding to set
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
There is no such Charset as gzip. This property has nothing to do with the message content, it is simply used when converting byte[] to/from String. It is UTF-8 by default.
This code below creates JMS queue at run time in Wildfly 9.0.1 with no problem. In Wildfly 10 and 11 hornetq-server was replaced with activemq. How properly migrate it to Wildfly 10/11?
Thank you.
private boolean createQueue(String operationName, String queueName) {
boolean result = false;
ModelControllerClient client = qService.getModelControllerClient();
if(client != null){
ModelNode operation = new ModelNode();
ModelNode address = operation.get(ClientConstants.OP_ADDR);
address.add("subsystem", "messaging");
address.add("hornetq-server", "default");
address.add("jms-queue", queueName);
ModelNode entries = operation.get("entries");
entries.add("jms/queue/" + queueName);
operation.get(ClientConstants.OP).set(operationName);
try {
ModelNode returnVal = client.execute(operation);
return returnVal.get("outcome").asString().equalsIgnoreCase("success");
} catch (Exception e) {
DLOG.error(ExceptionUtils.getStackTrace(e));
} finally {
try {
client.close();
} catch (IOException ex) {
DLOG.error(ExceptionUtils.getStackTrace(ex));
}
}
}
return result;
}
With Wildfly 10 the JMS-Implementation changed from HornetQ to Apache ActiveMQ Artemis.The following example is tested with Wildfly 10.
You could prepare the command to create a queue like this:
public void createQueue() throws Exception {
ModelControllerClient client = ModelControllerClient.Factory.create(InetAddress.getByName("localhost"), 9990);
if (client != null) {
ModelNode op = new ModelNode();
op.get(ClientConstants.OP_ADDR).add(ClientConstants.SUBSYSTEM, "messaging-activemq");
op.get(ClientConstants.OP_ADDR).add(ClientConstants.SERVER, "default");
op.get(ClientConstants.OP_ADDR).add("jms-queue", "HelloWorldQueue");
op.get("entries").add("queue/HelloWorldQueue");
op.get("entries").add("java:jboss/exported/queue/HelloWorldQueue");
op.get(ClientConstants.OP).set("add");
applyUpdate(op, client);
}
}
And execute the operation with this method:
private static void applyUpdate(ModelNode update, final ModelControllerClient client) throws IOException {
LOG.info("Execute: " + update.toString());
ModelNode result = client.execute(new OperationBuilder(update).build());
if (result.hasDefined("outcome") && "success".equals(result.get("outcome").asString())) {
if (result.hasDefined("result")) {
LOG.info(result.get("result").toString());
}
} else if (result.hasDefined("failure-description")) {
throw new RuntimeException(result.get("failure-description").toString());
} else {
throw new RuntimeException("Operation not successful; outcome = " + result.get("outcome"));
}
}
The code runs inside a WAR with the following maven dependency:
<dependency>
<groupId>org.wildfly.core</groupId>
<artifactId>wildfly-controller-client</artifactId>
<version>3.0.10.Final</version>
</dependency>
With Java EE 7 and JMS 2.0 there is as well the annotation #JMSDestinationDefinitions which allows automatic creation of JMS resources at deployment time. For some use cases this could already be good enough.
I am using Spring jmx to create jmx client which can interact with Cassandra cluster to get a mbean object attribute Livedicsspaceused.
So this Cassandra cluster had 3 node hence different serviceUrl (each having different ip address).
Now I realize that while creating MBeanServerConnectionFactoryBean bean I can specify only one service URl like below:
#Bean
MBeanServerConnectionFactoryBean getConnector() {
MBeanServerConnectionFactoryBean mBeanfactory = new MBeanServerConnectionFactoryBean();
try {
mBeanfactory.setServiceUrl("serviceUrl1");
} catch (MalformedURLException e) {
e.printStackTrace();
}
mBeanfactory.setConnectOnStartup(false);
return mBeanfactory;
}
Then in main I am accessing this as below:
objectName = newObjectName(QueueServicesConstant.MBEAN_OBJ_NAME_LIVE_DISC_USED);
long count = (Long)mBeanFactory.getObject().getAttribute(objectName, QueueServicesConstant.MBEAN_ATTR_NAME_COUNT);
How can i get this value in all three nodes?
You need 3 distinct connectors.
Or you can use something like a Jolokia Proxy to access multiple servers (using REST instead of JSR 160).
This is how I solved the problem ..Instead of using Spring-JMX, I am directly using javax.management apis..So my code below will get any one of the connector which will be sufficient to provide me correct attribute value however it will try to connect to ohther node if it fails to get connector from one server node.
#SuppressWarnings("restriction")
private Object getMbeanAttributeValue(String MbeanObectName,
String attributeName) throws IOException,
AttributeNotFoundException, InstanceNotFoundException,
MBeanException, ReflectionException, MalformedObjectNameException {
Object attributeValue = null;
JMXConnector jmxc = null;
try {
State state = metaTemplate.getSession().getState();
List<String> serviceUrlList = getJmxServiceUrlList(state
.getConnectedHosts());
jmxc = getJmxConnector(serviceUrlList);
ObjectName objectName = new ObjectName(MbeanObectName);
MBeanServerConnection mbsConnection = jmxc
.getMBeanServerConnection();
attributeValue = mbsConnection.getAttribute(objectName,
attributeName);
} finally {
if (jmxc != null)
jmxc.close();
}
return attributeValue;
}
// This will provide any one of the JMX Connector of cassandra cluster
#SuppressWarnings("restriction")
private JMXConnector getJmxConnector(List<String> serviceUrlList)
throws IOException {
JMXConnector jmxc = null;
for (String serviceUrl : serviceUrlList) {
JMXServiceURL url;
try {
url = new JMXServiceURL(serviceUrl);
jmxc = JMXConnectorFactory.connect(url, null);
return jmxc;
} catch (IOException e) {
log.error(
"getJmxConnector: Error while connecting to JMX sereice {} ",
serviceUrl, e.getMessage());
}
}
throw new IOException(
"Not able to connect to any of Cassandra JMX connector.");
}