Check MQ queue depth - java

Can anyone help in doing the code in java of getting the depth of the queues. We are having 4 queues in IBM WebSphere MQ and inside them there are messages.
I want to write a jsp to read the queue names and their depth while running the report.
How do I do that?

See http://blog.guymahieu.com/2008/06/11/getting-the-depth-of-an-mqseries-queue-from-java/.
I re-implemented this as follows:
import com.ibm.mq.*;
public class QueueManager {
private final String host;
private final int port;
private final String channel;
private final String manager;
private final MQQueueManager qmgr;
public QueueManager(String host, int port, String channel, String manager) throws MQException {
this.host = host;
this.port = port;
this.channel = channel;
this.manager = manager;
this.qmgr = createQueueManager();
}
public int depthOf(String queueName) throws MQException {
MQQueue queue = qmgr.accessQueue(queueName, MQC.MQOO_INQUIRE | MQC.MQOO_INPUT_AS_Q_DEF, null, null, null);
return queue.getCurrentDepth();
}
#SuppressWarnings("unchecked")
private MQQueueManager createQueueManager() throws MQException {
MQEnvironment.channel = channel;
MQEnvironment.port = port;
MQEnvironment.hostname = host;
MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
return new MQQueueManager(manager);
}
}
Put the following jars on your classpath:
com.ibm.mq*jar
j2ee.jar

I saw a response access queue with Websphere MQ API
Have you look at MBeans accessibles in JMX context ? If I had to do that I'll expose it in a Mbean.
You can see there IBM JMS Topologies
For monitoring and checking the status of resources, such as queue depths, there are a couple of options. The preferred option is to use the JMX Mbeans provided with Application Serve for monitoring: JMSBasicFunction, JMSAdministration, and EmbeddedJMSAdministration.
You can access these Mbeans through wsadmin or programmatically. Secondly, you can use the traditional WMQ administration utilities, such as runmqsc or MQExplorer, to look at queues and other resources. If you do use these utilities, it is essential that you do not make any configuration changes to the Application Server queue manager and queues. These resources are under the control of Application Server. Making changes to these resources using the MQ utilities results in a non-functioning configuration
Dont know if you are on a WAS server and if this is still the same MBeans, but you should find equivalents Mbeans on your AS.

Related

Springboot Cassandra - CqlSessionFactoryBean with SSL

Small question regarding how to connect to a Cassandra cluster that is SSL enabled please.
Currently, I am connecting to a Cassandra cluster that is not SSL enabled by doing the following, and it is working perfectly fine.
#Configuration
public class BaseCassandraConfiguration extends AbstractReactiveCassandraConfiguration {
#Value("${spring.data.cassandra.username}")
private String username;
#Value("${spring.data.cassandra.password}")
private String passPhrase;
#Value("${spring.data.cassandra.keyspace-name}")
private String keyspace;
#Value("${spring.data.cassandra.local-datacenter}")
private String datacenter;
#Value("${spring.data.cassandra.contact-points}")
private String contactPoints;
#Value("${spring.data.cassandra.port}")
private int port;
#Bean
#NonNull
#Override
public CqlSessionFactoryBean cassandraSession() {
final CqlSessionFactoryBean cqlSessionFactoryBean = new CqlSessionFactoryBean();
cqlSessionFactoryBean.setContactPoints(contactPoints);
cqlSessionFactoryBean.setKeyspaceName(keyspace);
cqlSessionFactoryBean.setLocalDatacenter(datacenter);
cqlSessionFactoryBean.setPort(port);
cqlSessionFactoryBean.setUsername(username);
cqlSessionFactoryBean.setPassword(passPhrase);
return cqlSessionFactoryBean;
}
I have another Cassandra cluster, that is SSL enabled.
I was expecting to see something like cqlSessionFactoryBean.setSSLEnabled(true), something like that. Unfortunately, it seems there is no such.
May I ask what is the proper way to set up this bean in order to connect to a Cassandra with SSL please?
Thank you.
The CqlSessionFactoryBean doesn't have a method for SSL connections, so you might have to change it and use CqlSession instead.
SSLContext sslContext = ...
CqlSession session = CqlSession.builder()
.withSslContext(sslContext)
.build();
or
SslEngineFactory yourFactory = ...
CqlSession session = CqlSession.builder()
.withSslEngineFactory(yourFactory)
.build();

OutOfMemoryError: Direct buffer memory when using websockets in WildFly

After a while on our WildFly 18 server, in production, we encountered this error:
[org.xnio.listener] (default I/O-1) XNIO001007: A channel event listener threw an exception:
java.lang.OutOfMemoryError: Direct buffer memory
at java.base/java.nio.Bits.reserveMemory(Bits.java:175)
at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118)
at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317)
at org.jboss.xnio#3.7.3.Final//org.xnio.BufferAllocator$2.allocate(BufferAllocator.java:57)
at org.jboss.xnio#3.7.3.Final//org.xnio.BufferAllocator$2.allocate(BufferAllocator.java:55)
at org.jboss.xnio#3.7.3.Final//org.xnio.ByteBufferSlicePool.allocateSlices(ByteBufferSlicePool.java:162)
at org.jboss.xnio#3.7.3.Final//org.xnio.ByteBufferSlicePool.allocate(ByteBufferSlicePool.java:149)
at io.undertow.core#2.0.27.Final//io.undertow.server.XnioByteBufferPool.allocate(XnioByteBufferPool.java:53)
at io.undertow.core#2.0.27.Final//io.undertow.server.protocol.framed.AbstractFramedChannel.allocateReferenceCountedBuffer(AbstractFramedChannel.java:549)
at io.undertow.core#2.0.27.Final//io.undertow.server.protocol.framed.AbstractFramedChannel.receive(AbstractFramedChannel.java:370)
at io.undertow.core#2.0.27.Final//io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:38)
at io.undertow.core#2.0.27.Final//io.undertow.websockets.core.AbstractReceiveListener.handleEvent(AbstractReceiveListener.java:33)
at org.jboss.xnio#3.7.3.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at io.undertow.core#2.0.27.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:950)
at io.undertow.core#2.0.27.Final//io.undertow.server.protocol.framed.AbstractFramedChannel$FrameReadListener.handleEvent(AbstractFramedChannel.java:931)
at org.jboss.xnio#3.7.3.Final//org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)
at org.jboss.xnio#3.7.3.Final//org.xnio.conduits.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.java:66)
at org.jboss.xnio.nio#3.7.3.Final//org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:89)
at org.jboss.xnio.nio#3.7.3.Final//org.xnio.nio.WorkerThread.run(WorkerThread.java:591)
We checked a JVM dump through jxray, and it seems websockets are the culprit:
Fact is that our websocket is kind of straightforward:
#ApplicationScoped
#ServerEndpoint(value = "/ws/messenger/{accountId}")
public class MessengerSocket implements Serializable
{
private static final long serialVersionUID = -3173234888004281582L;
#Inject
private Logger log;
#Inject
private MessengerHandler handler;
#OnOpen
public void onOpen(#PathParam("accountId") String accountId, Session session, EndpointConfig config)
{
log.debug("Opening for {}", accountId);
handler.subscribeSocket(session, UUID.fromString(accountId));
}
#OnClose
public void onClose(#PathParam("accountId") String accountId, Session session, CloseReason closeReason)
{
log.debug("Closing {}", accountId);
handler.unsubscribeSocket(session, UUID.fromString(accountId));
}
}
It's coupled with a simple handler, managing a map of users sessions:
#ApplicationScoped
public class MessengerHandler
{
#Inject
private Logger log;
// key: Account id
private Map<UUID, AccountMessengerSessions> sessions;
public void init()
{
sessions = new ConcurrentHashMap<>();
}
public void subscribeSocket(Session session, UUID accountId)
{
// build and store the account messenger session if new
AccountMessengerSessions messenger = sessions.getOrDefault(accountId, new AccountMessengerSessions(accountId));
messenger.getWsSessions().add(session);
sessions.putIfAbsent(accountId, messenger);
log.debug("{} has {} messenger socket session(s) (one added)", messenger.getAccountId(), messenger.getWsSessions().size());
}
/**
* Unsubscribes the provided WebSocket from the Messenger.
*/
public void unsubscribeSocket(Session session, UUID accountId)
{
if (!sessions.containsKey(accountId))
{
log.warn("Ignore unsubscription from {} socket, as {} is unknwon from messenger", session.getId(), accountId);
return;
}
AccountMessengerSessions messenger = sessions.get(accountId);
messenger.getWsSessions().remove(session);
log.debug("{} has {} messenger socket session(s) (one removed)", messenger.getAccountId(), messenger.getWsSessions().size());
if (!messenger.getWsSessions().isEmpty())
{
return;
}
// no more socket sessions, fully remove
sessions.remove(messenger.getAccountId());
}
}
Client side, we have a bit of javascript called when a page is loaded, again, nothing fancy:
var accountId = // some string found in DOM
var websocketUrl = "wss://" + window.location.host + "/ws/messenger/" + accountId;
var websocket = new WebSocket(websocketUrl);
websocket.onmessage = function (event) {
var data = JSON.parse(event.data);
// nothing fancy here...
};
Our users don't use a lot the feature offered by the websocket (an instant messenger), so what is really happening in production is basically websockets opening and closing at each page, with very few messages sent through.
Where could we get it wrong and create this buffer leak? Did we forget something critical?
Looking at this post this may happen if you have a lot of CPU. This was solved by decreasing the number of IO workers. Not sure if this can help in your case.
I also had a similar problem on our wildfly 18 (wildfly 19 suffers from it, too). It is probably triggered by a faulty xnio lib inside wildfly. After updating to wildfly 22 (using the latest xnio lib) the problem was gone.

MQ - Get Multi Instance MQ Manager Connection List

In a Java client app we are connecting to a multi-instance MQ Manager as follows:
java.net.URL ccdt = new URL("file:./config/qmgrs/MQMGR/AMQCLCHL.TAB");
MQQueueManager mqQueueManager = new MQQueueManager("*MQMGR", ccdt);
We can then for example enquire about the current depth of a queue as follows:
int openOptions = CMQC.MQOO_INQUIRE;
MQQueue mqQueue = mqQueueManager.accessQueue("A.QUEUE.NAME", openOptions);
System.out.println("queue depth:" + mqQueue.getCurrentDepth());
Question is, using the same MQQueueManager object, how can we get the list of multi-instance MQ Managers' addresses and ports. Or any other info about the manager itself...
We can see there is the following sort of thing available:
String nameList = mqQueueManager.getAttributeString(MQConstants.MQCA_NAMELIST_NAME, MQConstants.MQ_NAMELIST_NAME_LENGTH);
But when we call the above command, we get:
com.ibm.mq.MQException: MQJE001: Completion Code '2', Reason '2067'.
We are not sure if this is because the client code is not configured correctly or, if it is because the connection that we are using does not have sufficient permissions to get information about the manager?
You will have to use MQ PCF classes to query queue manager attributes. There is sample PCF_WalkThroughQueueManagerAttributes.java shipped with MQ that displays all attributes of queue manager. Here is small sample that lists local queues of a queue manager.
private void runPCFTest() {
try {
PCFAgent agent = new PCFAgent(connect());
PCFParameter[] parameters = { new MQCFST (MQConstants.MQCA_Q_NAME, "*"),
new MQCFIN (MQConstants.MQIA_Q_TYPE, MQConstants.MQQT_LOCAL)};
MQMessage[] responses = agent.send(CMQCFC.MQCMD_INQUIRE_Q_NAMES, parameters);
MQCFH cfh = new MQCFH(responses[0]);
for (int i = 0; i < cfh.getParameterCount(); i++) {
System.out.println (PCFParameter.nextParameter (responses [0]));
}
}catch(Exception ex) {
System.out.println(ex);
}
}
#SuppressWarnings({ "unchecked", "rawtypes" })
private MQQueueManager connect() throws MQException {
Hashtable props = new Hashtable();
props.put(MQConstants.HOST_NAME_PROPERTY, "localhost");
props.put(MQConstants.PORT_PROPERTY, 1414);
props.put(MQConstants.CHANNEL_PROPERTY, "MFT_CHN");
props.put(MQConstants.USER_ID_PROPERTY, "user1");
props.put(MQConstants.PASSWORD_PROPERTY, "passw0rd");
props.put(MQConstants.USE_MQCSP_AUTHENTICATION_PROPERTY, true);
return new MQQueueManager("MQM", props);
}
But why do you want to query connection information, host, port etc?
If I understand your question correctly, you want to know all of the hostnames (or IP addresses) and Port numbers of the servers where the MI queue manager may reside. Correct?
This information is in your CCDT file. When you (or MQAdmin) created your CCDT entry for the CLNTCONN (client-side channel), you would have issued a like:
DEFINE CHANNEL(TEST.CHL) CHLTYPE(CLNTCONN) TRPTYPE(TCP) CONNAME('ipaddr1(1414), ipaddr2(1414)') QMNAME(QM1)
Hence, the CONNAME parameter has the information and that is what the MQ client library uses to connect to the remote queue manager. First it will try 'ipaddr1(1414)' and if it fails then it will try 'ipaddr2(1414)'.

akka remote can't find

I am learning Akka remoting, referring to the book Learning Akka.
Using a limited network, I can't use sbt (can't config the proxy well).
First, I create a project for an Akka server with the application.conf
akka {
actor {
provider = remote
}
remote {
emabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "127.0.0.1"
port = 2552
}
}
}
and the console shows
Remoting now listens on addresses: [akka.tcp://akkademy#127.0.0.1:2552]
The second project is the client having a JClient class:
public class JClient {
private static final int TIMEOUT = 2000;
private final ActorSystem system = ActorSystem.create("LocalSystem");
private final ActorSelection remoteDb;
public JClient(String remoteAddress) {
remoteDb = system.actorSelection("akka.tcp://LocalSystem#" + remoteAddress + "/user/akkademy-db");
}
public CompletionStage set(String key, Object value) {
return toJava(ask(remoteDb, new SetRequest(key, value), TIMEOUT));
}
public CompletionStage<Object> get(String key) {
return toJava(ask(remoteDb, new GetRequest(key), TIMEOUT));
}
}
I pass the value "127.0.0.1:2552" to remoteAddress, calling the set/get methods, and encounter the error:
java.util.concurrent.ExecutionException: akka.pattern.AskTimeoutException: Ask timed out on [ActorSelection[Anchor(akka://akkademy/deadLetters), Path(/user/.*)]] after [2000 ms]. Sender[null] sent message of type "javah.GetRequest".
Your client code to obtain an ActorSelection to the remote actor is incorrect. Instead of "LocalSystem", which is the name of the client's actor system, use "akkademy", the name of the server's actor system. Change the JClient constructor to the following:
public JClient(String remoteAddress) {
remoteDb = system.actorSelection("akka.tcp://akkademy#" + remoteAddress + "/user/akkademy-db");
}
In actorSelection the selector should be string of format akka.tcp://${remoteActorSystemName}#${remoteAddress}/user/$actorPath. In the snippet you've posted, looks like you were using LocalSystem as ${remoteActorSystemName} instead of the remote actor system name.
Let me know if switching it to remote works, if not, can you post the full code you are using or a link to it ?

Akka HTTP server with SSL support in Java - How to create configuration?

I am trying to create an Akka HTTP server, which will support SSL.
I am aware of this question for scala Akka HTTP 2.0 to use SSL (HTTPS) and I am trying to work it into Java code but I am getting lost.
The DSL akka.http.javadsl.Http class is different for Java and requires akka.actor.ExtendedActorSystem, when I try to create an instance for it I am required to create an application configuration with the com.typesafe.config.Config class, which I can't figure out how to instantiate and what to put in it.
Is there any simpler way? Or any classes I can use to create all the required configurations?
This is a snippet of the code:
// boot up server using the route as defined below
final ActorSystem system = ActorSystem.create();
final ActorMaterializer materializer = ActorMaterializer.create(system);
// Run the server bound to the local machine IP
String hostAddress = InetAddress.getLocalHost().getHostAddress();
// No implementation here?????
Config applicationConfig = new Config() {
}
ExtendedActorSystem extendedActorSystem = new ActorSystemImpl("HttpProxy", applicationConfig, ClassLoader.getSystemClassLoader(), Option.empty());
// todo: missing handler, settings, httpsContext and log
Flow<HttpRequest, HttpResponse, ?> handler;
ServerSettings settings;
akka.japi.Option<HttpsContext> httpsContext;
LoggingAdapter log;
new Http(extendedActorSystem).bindAndHandle(handler, hostAddress, PORT, settings, httpsContext, log, materializer);
System.out.println("Starting server on " + hostAddress + ":" + PORT);
// The server would stop if carriage return is entered in the system cosole
System.out.println("Type RETURN to exit");
System.in.read();
system.shutdown();
It supposed to be something like this:
// boot up server using the route as defined below
// Run the server bound to the local machine IP
String hostAddress = InetAddress.getLocalHost().getHostAddress();
// No implementation here?????
Config applicationConfig = ConfigFactory.load();
ActorSystem system = ActorSystem.create("HttpProxy", applicationConfig);
final ActorMaterializer materializer = ActorMaterializer.create(system);
// todo: missing handler, settings, httpsContext and log
Flow<HttpRequest, HttpResponse, ?> handler;
ServerSettings settings;
akka.japi.Option<HttpsContext> httpsContext;
LoggingAdapter log;
Http.get(system).bindAndHandle(handler, hostAddress, 9000, settings, httpsContext, log, materializer);
System.out.println("Starting server on " + hostAddress + ":" + 9000);

Categories