Disable JMX/MBeans in JVM - jvm

I have two Debezium SQL Server connectors that have to connect to one database and publish two different tables. Their name and database.history.kafka.topic are unique. Still when adding the second one (using a POST request) I get below exceptions. I don't want to use a unique value for database.server.name which counterintuitively has been used for metric name.
java.lang.RuntimeException: Unable to register the MBean 'debezium.sql_server:type=connector-metrics,context=schema-history,server=mydatabase'
Caused by: javax.management.InstanceAlreadyExistsException: debezium.sql_server:type=connector-metrics,context=schema-history,server=mydatabase
We won't be using JMX/MBeans so it's okay to disable it, but the question is how. If there is a common way to do it for JVM please advise.
I even see below code in Debezium where it registers a MBean. Looking just at two first lines, it seems one way to bypass this issue is forcing ManagementFactory.getPlatformMBeanServer() to return null. So another way of asking the same question may be how to force ManagementFactory.getPlatformMBeanServer() return null?
public synchronized void register() {
try {
final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
if (mBeanServer == null) {
LOGGER.info("JMX not supported, bean '{}' not registered", name);
return;
}
// During connector restarts it is possible that Kafka Connect does not manage
// the lifecycle perfectly. In that case it is possible the old metric MBean is still present.
// There will be multiple attempts executed to register new MBean.
for (int attempt = 1; attempt <= REGISTRATION_RETRIES; attempt++) {
try {
mBeanServer.registerMBean(this, name);
break;
}
catch (InstanceAlreadyExistsException e) {
if (attempt < REGISTRATION_RETRIES) {
LOGGER.warn(
"Unable to register metrics as an old set with the same name exists, retrying in {} (attempt {} out of {})",
REGISTRATION_RETRY_DELAY, attempt, REGISTRATION_RETRIES);
final Metronome metronome = Metronome.sleeper(REGISTRATION_RETRY_DELAY, Clock.system());
metronome.pause();
}
else {
LOGGER.error("Failed to register metrics MBean, metrics will not be available");
}
}
}
// If the old metrics MBean is present then the connector will try to unregister it
// upon shutdown.
registered = true;
}
catch (JMException | InterruptedException e) {
throw new RuntimeException("Unable to register the MBean '" + name + "'", e);
}
}

You should use a single Debezium SQL Server connector for this, and use the table.include.list property on the connector to list the two tables you want to capture.
https://debezium.io/documentation/reference/stable/connectors/sqlserver.html#sqlserver-property-table-include-list

Related

Asynchronous programming for IotHub Device Registration in Java?

I am currently trying to implement the Java web service(Rest API) where the endpoint creates the device in the IoTHub and updates the device twin.
There are two methods available in the azure-iot sdk. One is
addDevice(deviceId, authenticationtype)
and another is to
addDeviceAsync(deviceId, authenticationtype)
I just wanted to figure out which one should I use in the web service(as a best practice). I am not very strong in MultiThreading/Concurrency so was wondering to receive people's expertise on this. Any suggestion/Link related to this is much appreciated
Thanks.
The Async version of AddDevice is basically the same. If you use AddDeviceAsync then a thread is created to run the AddDevice call so you are not blocked on it.
Check the code#L269 of RegistryManager doing exactly that: https://github.com/Azure/azure-iot-sdk-java/blob/master/service/iot-service-client/src/main/java/com/microsoft/azure/sdk/iot/service/RegistryManager.java#L269
public CompletableFuture<Device> addDeviceAsync(Device device) throws IOException, IotHubException
{
if (device == null)
{
throw new IllegalArgumentException("device cannot be null");
}
final CompletableFuture<Device> future = new CompletableFuture<>();
executor.submit(() ->
{
try
{
Device responseDevice = addDevice(device);
future.complete(responseDevice);
}
catch (IOException | IotHubException e)
{
future.completeExceptionally(e);
}
});
return future;
}
You can as well build your own async wrapper and call AddDevice() from there.

I need answer of one jade agent to depend on information from others and don't know how to do it

I'm new to jade and I have 5 agents in eclipse that have formula for finding an average and the question is how to send information from agent to this formula for calculation?
I'll be glad if someone can help me with this.
For example, there is one of my agents. There's no formula, because I don't know how to represent it. This is math expression of it: n+=alfa(y(1,2)-y(1,1))
public class FirstAgent extends Agent {
private Logger myLogger = Logger.getMyLogger(getClass().getName());
public class WaitInfoAndReplyBehaviour extends CyclicBehaviour {
public WaitInfoAndReplyBehaviour(Agent a) {
super(a);
}
public void action() {
ACLMessage msg = myAgent.receive();
if(msg != null){
ACLMessage reply = msg.createReply();
if(msg.getPerformative()== ACLMessage.REQUEST){
String content = msg.getContent();
if ((content != null) && (content.indexOf("What is your number?") != -1)){
myLogger.log(Logger.INFO, "Agent "+getLocalName()+" - Received Info Request from "+msg.getSender().getLocalName());
reply.setPerformative(ACLMessage.INFORM);
try {
reply.setContentObject(7);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else{
myLogger.log(Logger.INFO, "Agent "+getLocalName()+" - Unexpected request ["+content+"] received from "+msg.getSender().getLocalName());
reply.setPerformative(ACLMessage.REFUSE);
reply.setContent("( UnexpectedContent ("+content+"))");
}
}
else {
myLogger.log(Logger.INFO, "Agent "+getLocalName()+" - Unexpected message ["+ACLMessage.getPerformative(msg.getPerformative())+"] received from "+msg.getSender().getLocalName());
reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
reply.setContent("( (Unexpected-act "+ACLMessage.getPerformative(msg.getPerformative())+") )");
}
send(reply);
}
else {
block();
}
}
}
So from what I can make out you want to (1) send a formula/task to multiple platforms, (2) have them performed locally, (3) and have the results communicated back.
I think there are atleast two ways of doing this:
The first is sending an object in an ACLMessage using Java Serialisation. This is a more OOP approach and not very "Agenty".
The second being the cloning or creating a local task agent.
Using Java SerialZation. (Solution 1)
Create an object for the calculation
class CalculationTask implements serialization
{ int n;
int calculate(){
n+=alfa(y(1,2)-y(1,1));
}
}
send the calculation object via ACLMESSAGE from the senderAgent.
request.setContentObject(new CalculationTask())
recieve the calculation object by recieverAgent and perform calculation on the object. Then response setting the complete task in the response.
CalculationTask myTask = request.getContentObject();
myTask.calculate();
ACLMESSAGE response = request.createReply();
response.setContentObject(myTask());
response.setPerformative(ACLMESSAGE.INFORM)
send(response)
The senderAgent then receives the complete job.
ACLMESSAGE inform = getMessage();
CalculationTask completeTask = inform.getContentObject();
completeTask.process()
Creating local Task Agents (Solution 2)
The Agent Orientated way of doing it would be to launch a task agent on each platform. Have each task agent complete the task and respond appropriately.

test if jms listener is working

i want to test if the JMS listener is working !
to do that i want to test if the Queue size do not change for more than 5 seconds that means that the listener is not working
what should i add to my code please
try {
if ((msgIdMap.contains(tm.getJMSMessageID())) || !(message instanceof TextMessage)) {
System.out.println("\tListener not working !");
} else {
process((TextMessage) message);
}
If the listener is designed, coded and configured correctly it should be working unless there's a problem with the provider. If there is a problem with the provider, the client portion of the provider should detect it and call your ExceptionListener, if it is defined.
So, I would provide an ExceptionListener, by having your class implement the ExceptionListener:
public class MyJMSClass implements javax.jms.ExceptionListener {
then set the listener on the connection to this class:
connection.setExceptionListener(this);
then provide the recovery code:
public void onException(JMSException jmse) {
log.error("JMS exception has occured.. ", jmse);
// handle exception appropriately, perhaps by attempting to reconnect
}

How can a RabbitMQ Client tell when it loses connection to the server?

If I'm connected to RabbitMQ and listening for events using an EventingBasicConsumer, how can I tell if I've been disconnected from the server?
I know there is a Shutdown event, but it doesn't fire if I unplug my network cable to simulate a failure.
I've also tried the ModelShutdown event, and CallbackException on the model but none seem to work.
EDIT-----
The one I marked as the answer is correct, but it was only part of the solution for me. There is also HeartBeat functionality built into RabbitMQ. The server specifies it in the configuration file. It defaults to 10 minutes but of course you can change that.
The client can also request a different interval for the heartbeat by setting the RequestedHeartbeat value on the ConnectionFactory instance.
I'm guessing that you're using the C# library? (but even so I think the others have a similar event).
You can do the following:
public class MyRabbitConsumer
{
private IConnection connection;
public void Connect()
{
connection = CreateAndOpenConnection();
connection.ConnectionShutdown += connection_ConnectionShutdown;
}
public IConnection CreateAndOpenConnection() { ... }
private void connection_ConnectionShutdown(IConnection connection, ShutdownEventArgs reason)
{
}
}
This is an example of it, but the marked answer is what lead me to this.
var factory = new ConnectionFactory
{
HostName = "MY_HOST_NAME",
UserName = "USERNAME",
Password = "PASSWORD",
RequestedHeartbeat = 30
};
using (var connection = factory.CreateConnection())
{
connection.ConnectionShutdown += (o, e) =>
{
//handle disconnect
};
using (var model = connection.CreateModel())
{
model.ExchangeDeclare(EXCHANGE_NAME, "topic");
var queueName = model.QueueDeclare();
model.QueueBind(queueName, EXCHANGE_NAME, "#");
var consumer = new QueueingBasicConsumer(model);
model.BasicConsume(queueName, true, consumer);
while (!stop)
{
BasicDeliverEventArgs args;
consumer.Queue.Dequeue(5000, out args);
if (stop) return;
if (args == null) continue;
if (args.Body.Length == 0) continue;
Task.Factory.StartNew(() =>
{
//Do work here on different thread then this one
}, TaskCreationOptions.PreferFairness);
}
}
}
A few things to note about this.
I'm using # for the topic. This grabs everything. Usually you want to limit by a topic.
I'm setting a variable called "stop" to determine when the process should end. You'll notice the loop runs forever until that variable is true.
The Dequeue waits 5 seconds then leaves without getting data if there is no new message. This is to ensure we listen for that stop variable and actually quit at some point. Change the value to your liking.
When a message comes in I spawn the handling code on a new thread. The current thread is being reserved for just listening to the rabbitmq messages and if a handler takes too long to process I don't want it slowing down the other messages. You may or may not need this depending on your implementation. Be careful however writing the code to handle the messages. If it takes a minute to run and your getting messages at sub-second times you will run out of memory or at least into severe performance issues.

JMS Expiration after it has been receive not working

The title might be confusing but this is what I want to accomplish. I want to send a jms message from 1 ejb to another, the 2nd ejb has a message listener and this is now working properly. But I wanted the 1st ejb to create a temporary destination queue where the 2nd ejb would respond - this is also working properly.
My problem is in the 2nd ejb, it's calling a 3rd party web service that on some occasion would respond after a long time, and the temporary queue should expire on that time. But the problem is it doesn't according to java.net: http://java.net/projects/mq/lists/users/archive/2011-07/message/22
The message hasn't been delivered to a client and it expires -- in this case, the message is deleted when TTL is up.
The message is delivered to the JMS client (it's in-flight). Once this happens, since control is handed to the jms client, the broker cannot expire the message.
Finally, the jms client will check TTL just before it gives the message to the user application. If it's expired, we will not give it to the application and it will send a control message back to the broker indicating that the message was expired and not delivered.
So, it was received but no reply yet. Then on the time where it would write to the temporary queue it should already be expired but for some reason I was still able to write to the queue and I have the ff in my imq log:
1 messages not expired from destination jmsXXXQueue [Queue] because they have been delivered to client at time of the last expiration reaping
Is there another implementation where I can detect if the temporary queue is already expired? So that I can perform another set of action? Because my problem right now is ejb2 respond late and there is no more jms reader from ejb1 because it's already gone.
It works now, my solution was to wrap the 1st Stateless bean (the one where the first jms message originates) inside a bean managed transaction. See code below:
#Stateless
#TransactionManagement(TransactionManagementType.BEAN)
#LocalBean
public class MyBean {
public void startProcess() {
Destination replyQueue = send(jmsUtil, actionDTO);
responseDTO = readReply(jmsUtil, replyQueue, actionDTO);
jmsUtil.dispose();
}
public Destination send(JmsSessionUtil jmsUtil, SalesOrderActionDTO soDTO) {
try {
utx.begin();
jmsUtil.send(soDTO, null, 0L, 1,
Long.parseLong(configBean.getProperty("jms.payrequest.timetolive")), true);
utx.commit();
return jmsUtil.getReplyQueue();
} catch (Exception e) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
return null;
}
public ResponseDTO readReply(JmsSessionUtil jmsUtil, Destination replyQueue,
SalesOrderActionDTO actionDTO) {
ResponseDTO responseDTO = null;
try {
utx.begin();
responseDTO = (ResponseDTO) jmsUtil.read(replyQueue);
if (responseDTO != null) {
//do some action
} else { // timeout
((TemporaryQueue) replyQueue).delete();
jmsUtil.dispose();
}
utx.commit();
return responseDTO;
} catch (Exception e) {
try {
utx.rollback();
} catch (Exception e1) {
}
}
return responseDTO;
}
}