I want to discover all the destinations from solace (queues and topics)
I tried using MBeanServerConnection and query after names (but I didn't find a proper way to use this) or JNDI lookups Destination dest = (Destination) context.lookup(Dest_name), but I don't have the names of the queues/topics.
I am using solace - jms library.
I am searching for smth like this: (but for solace, not activeMq)
get all Queue from activeMQ
You will need to make use of SEMP over the management interface for this.
Sample commands:
curl -d '<rpc><show><queue><name>*</name></queue></show></rpc>' -u semp_username:semp_password http://your_management_ip:your_management_port/SEMP
curl -d '<rpc><show><topic-endpoint><name>*</name></topic-endpoint></show></rpc>' -u semp_username:semp_password http://your_management_ip:your_management_port/SEMP
Note that I'm using curl for simplicity, but any application can perform HTTP POSTs to execute these commands.
If you are using Java, you can refer to the SempHttpSetRequest sample found within the Solace API samples.
Documentation on SEMP can be found here.
However, the larger question here is why do you need to discover all destinations?
One of the features of the message broker is to decouple the publishers and consumers.
If you need to know if your persistent message is being published to a topic with no consumers, you can make use of the reject-msg-to-sender-on-no-subscription-match setting in the publishing application's client-profile.
This means that the publisher will obtain a negative acknowledgement in the event that it tries to publish a message on a topic that has no matching subscribers.
You can refer to "Handling Guaranteed Messages with No Matches" at https://docs.solace.com/Configuring-and-Managing/Configuring-Client-Profiles.htm for further details.
Here is some source code that might help. With the appliance configured correctly, SEMP is also available over JMS on topic "#SEMP/(router)/SHOW".
/**
* Return the SolTopicInfo for this topic (or all topics if 'topic' is null).
*
* #param session
* #param endpointName
* #return
*/
public static SolTopicInfo[] getTopicInfo(JCSMPSession session, String endpointName, String vpn,
String sempVersion) {
XMLMessageConsumer cons = null;
XMLMessageProducer prod = null;
Map<String, SolTopicInfo> tiMap = new HashMap<String, SolTopicInfo>();
try {
// Create a producer and a consumer, and connect to appliance.
prod = session.getMessageProducer(new PubCallback());
cons = session.getMessageConsumer(new SubCallback());
cons.start();
if (vpn == null) vpn = (String) session.getProperty(JCSMPProperties.VPN_NAME);
if (sempVersion == null) sempVersion = getSempVersion(session);
// Extract the router name.
final String SEMP_SHOW_TE_TOPICS = "<rpc semp-version=\""
+ sempVersion
+ "\"><show><topic-endpoint><name>"
+ endpointName
+ "</name><vpn-name>"+ vpn + "</vpn-name></topic-endpoint></show></rpc>";
RpcReply teTopics = sendRequest(session, SEMP_SHOW_TE_TOPICS);
for (TopicEndpoint2 te : teTopics.getRpc().getShow().getTopicEndpoint().getTopicEndpoints()
.getTopicEndpointArray()) {
SolTopicInfo ti = new SolTopicInfo();
ti.setBindCount(te.getInfo().getBindCount());
//qi.setDescription(qt.getInfo().getNetworkTopic());
ti.setEndpoint(te.getName());
ti.setMessageVPN(te.getInfo().getMessageVpn());
ti.setTopic(te.getInfo().getDestination());
ti.setDurable(te.getInfo().getDurable());
ti.setInSelPres(te.getInfo().getIngressSelectorPresent());
ti.setHwmMB(formatter.format(te.getInfo().getHighWaterMarkInMb()));
ti.setSpoolUsageMB(formatter.format(te.getInfo().getCurrentSpoolUsageInMb()));
ti.setMessagesSpooled(te.getInfo().getNumMessagesSpooled().longValue());
String status = te.getInfo().getIngressConfigStatus().substring(0, 1).toUpperCase();
status += " " + te.getInfo().getEgressConfigStatus().substring(0, 1).toUpperCase();
status += " " + te.getInfo().getIngressSelectorPresent().substring(0, 1).toUpperCase();
status += " " + te.getInfo().getType().substring(0, 1).toUpperCase();
ti.setStatus(status);
tiMap.put(ti.getEndpoint(), ti);
}
} catch (JCSMPException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (cons != null)
cons.close();
if (prod != null)
prod.close();
}
return tiMap.values().toArray(new SolTopicInfo[0]);
}
/**
* Return the SolQueueInfo for this queue (or all queues if 'queue' is null).
*
* #param session
* #param queue
* #param vpn (if null, use the session's vpn name)
* #param sempVersion, if null use 'soltr/7_1_1'
* #return
*/
public static SolQueueInfo[] getQueueInfo(JCSMPSession session, String queue, String vpn,
String sempVersion) {
XMLMessageConsumer cons = null;
XMLMessageProducer prod = null;
Map<String, SolQueueInfo> qiMap = new HashMap<String, SolQueueInfo>();
try {
// Create a producer and a consumer, and connect to appliance.
prod = session.getMessageProducer(new PubCallback());
cons = session.getMessageConsumer(new SubCallback());
cons.start();
if (vpn == null) vpn = (String) session.getProperty(JCSMPProperties.VPN_NAME);
if (sempVersion == null) sempVersion = getSempVersion(session);
// Extract the router name.
final String SEMP_SHOW_QUEUE_SUBS = "<rpc semp-version=\""
+ sempVersion
+ "\"><show><queue><name>"
+ queue
+ "</name><vpn-name>"+ vpn + "</vpn-name><subscriptions/><count/><num-elements>200</num-elements></queue></show></rpc>";
RpcReply queueSubs = sendRequest(session, SEMP_SHOW_QUEUE_SUBS);
for (QueueType qt : queueSubs.getRpc().getShow().getQueue().getQueues().getQueueArray()) {
SolQueueInfo qi = new SolQueueInfo();
qi.setBindCount(qt.getInfo().getBindCount());
//qi.setDescription(qt.getInfo().getNetworkTopic());
qi.setName(qt.getName());
qi.setMessageVPN(qt.getInfo().getMessageVpn());
qi.setDurable(qt.getInfo().getDurable());
qi.setEgSelPres(qt.getInfo().getEgressSelectorPresent());
qi.setHwmMB(formatter.format(qt.getInfo().getHighWaterMarkInMb()));
qi.setMessagesSpooled(qt.getInfo().getNumMessagesSpooled().longValue());
qi.setSpoolUsageMB(formatter.format(qt.getInfo().getCurrentSpoolUsageInMb()));
String status = qt.getInfo().getIngressConfigStatus().substring(0, 1).toUpperCase();
status += " " + qt.getInfo().getEgressConfigStatus().substring(0, 1).toUpperCase();
status += " " + qt.getInfo().getAccessType().substring(0, 1).toUpperCase();
status += " " + qt.getInfo().getEgressSelectorPresent().substring(0, 1).toUpperCase();
status += " " + qt.getInfo().getType().substring(0, 1).toUpperCase();
status += qt.getInfo().getDurable() ? " D" : " N";
qi.setStatus(status);
for (Subscription sub : qt.getSubscriptions().getSubscriptionArray()) {
qi.addSubscription(sub.getTopic());
}
qiMap.put(qi.getName(), qi);
}
} catch (JCSMPException e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
if (cons != null)
cons.close();
if (prod != null)
prod.close();
}
return qiMap.values().toArray(new SolQueueInfo[0]);
}
private static String getSempVersion(JCSMPSession session)
{
String retval = "soltr/7_1_1";
try {
String peerVersion = (String)session.getCapability(CapabilityType.PEER_SOFTWARE_VERSION);
if (peerVersion != null)
{
retval = "soltr/";
String[] version = peerVersion.split("\\.");
retval += version[0];
retval += "_" + version[1];
if (!version[2].equals("0")) retval += "_" + version[2];
}
} catch (Throwable e) {
System.err.println(e);
}
return retval;
}
private static RpcReply sendRequest(JCSMPSession session,
final String requestStr) {
try {
// Set up the requestor and request message.
String routerName = (String) session
.getCapability(CapabilityType.PEER_ROUTER_NAME);
final String SEMP_TOPIC_STRING = String.format("#SEMP/%s/SHOW",
routerName);
final Topic SEMP_TOPIC = JCSMPFactory.onlyInstance().createTopic(
SEMP_TOPIC_STRING);
Requestor requestor = session.createRequestor();
BytesXMLMessage requestMsg = JCSMPFactory.onlyInstance().createMessage(
BytesXMLMessage.class);
requestMsg.writeAttachment(requestStr.getBytes());
BytesXMLMessage replyMsg = requestor
.request(requestMsg, 5000, SEMP_TOPIC);
String replyStr = new String();
if (replyMsg.getAttachmentContentLength() > 0) {
byte[] bytes = new byte[replyMsg.getAttachmentContentLength()];
replyMsg.readAttachmentBytes(bytes);
replyStr = new String(bytes, "US-ASCII");
}
RpcReplyDocument doc = RpcReplyDocument.Factory.parse(replyStr);
RpcReply reply = doc.getRpcReply();
if (reply.isSetPermissionError()) {
throw new RuntimeException(
"Permission Error: Make sure SEMP over message bus SHOW commands are enabled for this VPN");
}
if( reply.isSetParseError() ) {
throw new RuntimeException( "SEMP Parse Error: " + reply.getParseError() );
}
if( reply.isSetLimitError() ) {
throw new RuntimeException( "SEMP Limit Error: " + reply.getLimitError() );
}
if( reply.isSetExecuteResult() && reply.getExecuteResult().isSetReason() ) { // axelp: encountered this error on invalid 'queue' name
throw new RuntimeException( "SEMP Execution Error: " + reply.getExecuteResult().getReason() );
}
return reply;
} catch (JCSMPException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (XmlException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
You can get message VPN specific queues and topics using following SEMPv2 command.
curl -s -X GET -u semp_user:semp_pass management_host:management_port/SEMP/v2/monitor/msgVpns/{vpn-name}/queues?select="queueName"
curl -s -X GET -u semp_user:semp_pass management_host:management_port/SEMP/v2/monitor/msgVpns/{vpn-name}/topicEndpoints?select="topicEndpointName"
Related
The following java code lists all the bare metal servers in softlayer for a specific SL account and filters for servers which are powered on (e.g. powerState='on'.
public void listServers(Account.Service service, ApiClient client) throws Exception {
service.withMask().hardware().fullyQualifiedDomainName().primaryIpAddress();
service.withMask().hardware().hardwareStatus();
service.withMask().hardware().id();
Account account = service.getObject();
//
// list of softlayer servers for the client account
//
for (Hardware hardware : account.getHardware()) {
String hostname = hardware.getFullyQualifiedDomainName();
String hardwareStatus = (hardware.getHardwareStatus() == null) ? null : hardware.getHardwareStatus().getStatus();
Long serverId = hardware.getId();
String powerState = null;
if (serverId != null) {
Hardware.Service hardwareService = Hardware.service(client, serverId);
hardwareService.setMask("mask[serverPowerState");
try {
powerState = hardwareService.getServerPowerState();
} catch (Exception ex) {
System.out.println("Error, cannot get powerState, hostname=" + hostname + ", msg=" + ex.getMessage());
}
}
System.out.println("Hostname=" + hostname + ", hwStatus=" + hardwareStatus + ", powerState=" + powerState);
}
}
Code seems to work, but for at least one of the servers, it fails on the call to hardwareService.getServerPowerState()
"Unable to establish IPMI v2 / RMCP+ session".
Any ideas why this is failing ?
I want to wait until my processes finish before I return my speechlet response, otherwise it seems to cut my process off and thus, not complete it, I actually believe it may freeze the process, but thats not my desire.
How do I go about waiting?
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
CommissionTicket commissionTicket = new CommissionTicket(sender);
commissionTicket.create();
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
UPDATE:
Had a look at the CloudWatch logs, and well, pretty much what I expected was happening is happening... have a look at the times for these logs (I ran them 3 different times, so 3 different times are logged, but apart of the same lambda session)
public void create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).queue(channel -> {
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
}
);
Logs:
https://gyazo.com/0ad2baa8d1438be8364dd1112159c4f4
https://gyazo.com/e197f33335046afe3c9f8f1ace267d30
UPDATE
Implemented the Future class, worked, but still a bit buggy.
It now completely creates the ticket, which is great, however, when I go to send the same call again, it for some reason sends a message in the same channel before preceding to create the next ticket.
So, to simulate...
Function call through AWS Lambda
Creates ticket completely
Function call through AWS Lambda again
Sends a message or two in the previous tickets channel
Creates new ticket completely
https://gyazo.com/dc6e4391f4964f41a73f1c3be92190f9
#Override
public SpeechletResponse onIntent(SpeechletRequestEnvelope<IntentRequest> requestEnvelope) {
IntentRequest request = requestEnvelope.getRequest();
Intent intent = request.getIntent();
String intentName = (intent != null) ? intent.getName() : null;
if (intentName == null) return null;
switch (intentName) {
case IntentTitle.NEW_TICKET:
switch (request.getDialogState()) {
case STARTED:
return Response.getDialogueResponse(intent, true);
case IN_PROGRESS:
return Response.getDialogueResponse(intent, false);
case COMPLETED:
String numberString = intent.getSlot(SlotTitle.ID).getValue();
if (!NumberUtils.isCreatable(numberString)) return Response.ERROR;
Member member = Info.GUILD.getMemberById(numberString);
User sender = UserDB.getUser(member);
System.out.println("log1");
Future<Ticket> commissionTicket = new CommissionTicket(sender).create();
try {
commissionTicket.get(10000, TimeUnit.MILLISECONDS);
} catch (Exception e) {
e.printStackTrace();
}
//wait until processes finish before continuing
return Response.NEW_TICKED_CREATED;
}
}
return null;
}
In the Ticket class:
public Future<Ticket> create() {
System.out.println("log2");
GuildController guildController = Info.GUILD.getController();
RequestFuture<Channel> channelRequestFuture = guildController.createTextChannel(ticketType.name().toLowerCase() + "-" + creator.getName() + "-" + id.value()).submit();
try {
Channel channel = channelRequestFuture.get(10000, TimeUnit.MILLISECONDS);
System.out.println("log3");
ChannelManager channelManager = channel.getManager();
GuildManager guildManager = channelManager.getGuild().getManager();
List<Member> members = guildManager.getGuild().getMembers();
List<Member> admins = new ArrayList<>();
for (Member member : members) {
for (Role role : member.getRoles()) {
if (!role.getName().equalsIgnoreCase(Info.ADMIN_STRING)) continue;
admins.add(member);
}
}
System.out.println("log4");
for (Member member : members) {
if (member.equals(creator.getMember())) continue;
channel.createPermissionOverride(member).setDeny(Permission.MESSAGE_READ).queue();
}
System.out.println("log5");
for (Member admin : admins) {
if (admin.equals(creator.getMember())) continue;
channel.createPermissionOverride(admin).setAllow(Permission.MESSAGE_READ).queue();
}
System.out.println("log6");
BotMessage botMessage = new BotMessage();
botMessage
.setTitle("New Ticket! User: " + creator.getName())
.setColour(Color.CYAN)
.setDescription("Please enter your full request here! \n" +
"Make sure to let us know whether you are looking for a quote/timeframe,\n" +
"or have a budget in mind, and we will work around you!\n\n" +
"A sales representative will be with you as soon as possible!")
.send((TextChannel) channel);
System.out.println("log7");
this.textChannel = (TextChannel) channel;
TicketDB.addTicket(this);
System.out.println("log8");
Future<Ticket> future = ConcurrentUtils.constantFuture(this);
return future;
} catch (Exception e) {
e.printStackTrace();
}
if (!userIsInTicket(creator)) users.add(creator);
return null;
}
I'm not sure what's going on inside commissionTicket.create(); (I assume it's your code, not part of some library, and that it's running asynchronously somehow), but one solution would be to have that method return a Future<> object and then wait on it to finish. Something along the lines of:
Future<CommissionTicket> commissionTicketFuture = CommissionTicket.create(sender);
commissionTicketFuture.get(SOME_TIMEOUT, TimeUnit.MILLIS);
return Response.NEW_TICKET_CREATED;
I have below code from my function where i am trying to take the parameters from database that is MAX_FAILED_ATTEMPT and based on this i will be going to send an alert if the check gets failed. The current code will try to take the value from MAX_FIELD_ATTEMPT and check immediately after one another. Now i just want to put the sleep after every attempt for 5 minutes. So for example if the MAX_FAILED_ATTEMPT is 3 then for first attempt it will try to check immediately,again it will sleep for 5 minutes and try to check,in this way based on interval it will try to check the the number of times for MAX_FAILED_ATTEMPT.
private String connect(KpiDefinition kpiDef)
{
FtpSftpServer ftpSftpServer = kpiDef.getFtpSftpServer();
// FTP key
String serverName = ftpSftpServer.getServerName();
// Retrieving ftp details from rator retail db
Map<String, String> serverDetails = getServerDetailsFromRator(kpiDef,
serverName);
if (serverDetails == null || serverDetails.isEmpty())
{
errorMessage = "Error while retrieving FTP Details from Retail DB.";
logger.debug(errorMessage);
} else
{
boolean success = false;
// We would attempt to connect till the max failed attempts
// defined on the resource are reached. However if the
// connection is already successful or if the connection has
// failed due to Authentication Failure, then we will not try
// again and simply come out of the loop.
Long maxFailedAttempts = kpiDef.getFtpSftpServer()
.getMaxFailedAttempts();
if (maxFailedAttempts == null || maxFailedAttempts == 0)
{
maxFailedAttempts = 1l;
}
for (int i = 0; i < maxFailedAttempts; i++)
{
try
{
success = connect(serverName, protocol, serverAddress,
serverPort, username, password);
if (!success)
{
String message = "Could not connect to " + protocol
+ " server " + serverName
+ " - Authorization failed.";
logger.debug(message);
errorMessage = message;
deactivateKPI(kpiDef, authenticateFailedMessage);
// do not attempt to try again if the KPI fails with
// authentication Exception.
break;
}
// Also come out of the loop if the connection was
// successful. We do not need to continue to attempt to
// connect.
break;
}
}
}
TimeUnit.MINUTES.sleep(5) in the locations you deem appropriate
Edit:
I would try changing the success conditional in your for loop just a little bit
for (int i = 0; i < maxFailedAttempts; i++)
{
try
{
success = connect(serverName, protocol, serverAddress,
serverPort, username, password);
if (!success)
{
String message = "Could not connect to " + protocol
+ " server " + serverName
+ " - Authorization failed.";
logger.debug(message);
errorMessage = message;
try
{
deactivateKPI(kpiDef, authenticateFailedMessage);
TimeUnit.MINUTES.sleep(5);
}
catch (AuthenticationException ae)
{
// do not attempt to try again if the KPI fails with
// authentication Exception.
ae.printStackTrace();
}
break;
}
// Also come out of the loop if the connection was
// successful. We do not need to continue to attempt to
// connect.
break;
}
}
I have a web app which uses JNDI for connection polling (DB server is MySql),
There is many request to web application and it has a web service used by one other web application.
It work fine but after a while in not works and after some no-processed commands in web service, the error below appears:
java.sql.SQLException: Cannot get a connection, general error
javax.naming.NameNotFoundException: Name [java:/comp/env] is not bound in this Context. Unable to find [java:].
I copy app aout put in below.
please notice i force app to print "+++++=====>>>> number of connection X"
when for new connection ( if it was new connection X increased)
and after closing connection "------=====>>>> number of connection X"
note 2: Whenever web service is called a "%%%%>>>>> web Service request for" string will be printed in the out put and then a "SELECT" command will run and print in the out put,but when system crashed the request to the web service received, but not proceed.
So look up for "+++++=====>>>>" and "+++++=====>>>>" and pay attention in defrence between "%%%%>>>>> web Service request for" in the beginning and at the end.
The out put is like below:
java out put file
public void close() throws SQLException {
connection.close();
counter--;
ServerLog.Print("------=====>>>> number of connection " + counter);
ServerLog.Print("Database connection is closed ...");
}
This are some methods in below:
public jjDatabaseWeb() throws SQLException, NamingException {
ctx = new InitialContext();
Context initCtx = (Context) ctx.lookup("java:/comp/env");
DataSource ds = (DataSource) initCtx.lookup("jdbc/MyDB");
connection = ds.getConnection();
counter++;
ServerLog.Print("+++++=====>>>> number of connection " + counter);
}
And in below is web service method that which calls whit other services in LAN :
/**
* this Method returns a string result; if(result =="" OR result==null){ do
* your work }else{ show user result as message (result is HTML ) }
*
* #param stdNubmer
* #param nationalId Is not important
* #return String result (as HTML )
* #throws javax.naming.NamingException
*/
#WebMethod(operationName = "studentCheck")
public String studentCheck(#WebParam(name = "stdNubmer") String stdNubmer, #WebParam(name = "nationalId") String nationalId) {
try {
ServerLog.Print("%%%%>>>>> web Service request for :" + stdNubmer);
try {
jjDatabaseWeb db = new jjDatabaseWeb();
DefaultTableModel dtm = db.Select(StdInfo.tableName, StdInfo._step + "," + StdInfo._alerts + "," + StdInfo._lastAertDate + "," + StdInfo._name + "," + StdInfo._family, StdInfo._stdNumber + "=" + stdNubmer);
List<Map<String, Object>> row = jjDatabaseWeb.separateRow(dtm);
db.close();//
if (row.size() == 1) {
if (!row.get(0).get(StdInfo._step).toString().equalsIgnoreCase("5")) {
int date = new jjCalendar_IR().getDBFormat_8length();
int lastAlertDate = Integer.parseInt(row.get(0).get(StdInfo._lastAertDate).toString());
int alerts = Integer.parseInt(row.get(0).get(StdInfo._alerts).toString());
if ((date - 5) <= lastAlertDate) {
return "";
}
StringBuilder html = new StringBuilder("");
html.append("<HTML>...</HTML>");
return html.toString();
}
}
return "";
} catch (NamingException ex) {
Logger.getLogger(csaWebService.class.getName()).log(Level.SEVERE, null, ex);
}
} catch (SQLException ex) {
Logger.getLogger(csaWebService.class.getName()).log(Level.SEVERE, null, ex);
ServerLog.Print(ex);
Server.ErrorHandler(ex);
return "";
}
return "";
}
}
There was so many connections that witch opened and not closed .
Be careful about close() for connections.
I am getting too many deadlocks on OrientDb while I am using Java API to query the vertices. After the deadlock happens, the entire database becomes unresponsive and I have to kill the daemon and start again. As example, the error that I get from deadlocks is :
com.orientechnologies.common.concur.OTimeoutException: Can not lock record for 2000 ms. seems record is deadlocked by other record
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.acquireReadLock(OAbstractPaginatedStorage.java:1300)
at com.orientechnologies.orient.core.tx.OTransactionAbstract.lockRecord(OTransactionAbstract.java:120)
at com.orientechnologies.orient.core.id.ORecordId.lock(ORecordId.java:282)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.lockRecord(OAbstractPaginatedStorage.java:1776)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.readRecord(OAbstractPaginatedStorage.java:1416)
at com.orientechnologies.orient.core.storage.impl.local.OAbstractPaginatedStorage.readRecord(OAbstractPaginatedStorage.java:694)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.executeReadRecord(ODatabaseDocumentTx.java:1569)
at com.orientechnologies.orient.core.tx.OTransactionNoTx.loadRecord(OTransactionNoTx.java:80)
at com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx.load(ODatabaseDocumentTx.java:1434)
at com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary.readRecord(ONetworkProtocolBinary.java:1456)
at com.orientechnologies.orient.server.network.protocol.binary.ONetworkProtocolBinary.executeRequest(ONetworkProtocolBinary.java:346)
at com.orientechnologies.orient.server.network.protocol.binary.OBinaryNetworkProtocolAbstract.execute(OBinaryNetworkProtocolAbstract.java:216)
at com.orientechnologies.common.thread.OSoftThread.run(OSoftThread.java:65)
Following is the block that I use to query edges and create associations between vertices
public User generateFriend(String mobile, String userRID) {
StringBuilder errorMsg = new StringBuilder();
Iterable<OrientVertex> vertexes;
//Retrieve friends of the user
List<User> friendsList = new ArrayList<User>();
vertexes = db.queryVertices("select expand( unionAll(inE('E_Friend').out,outE('E_Friend').in) ) from " + userRID,errorMsg);
if (!errorMsg.toString().equals("")) {
throw new DbException("Db exception occured, " + errorMsg);
}
for (OrientVertex v : vertexes){
friendsList.add(vertexToUser(v));
}
//Create edges if between the user and other users with mobile number in the list and if the edge is not yet created
User u = findUserByMobileNo(friendsList,mobile);
if ( u == null){
u = findByMobileNo(mobile);
if (u != null) {
//create edge
db.executeQuery("select createEdge('E_Friend','" + userRID + "','" + u.getRid() + "') from " + userRID, new HashMap<String, Object>(), errorMsg);
if (!errorMsg.toString().equals("")) {
throw new DbException("Db exception occured, " + errorMsg);
}
}
}
return u;
}
public Iterable<OrientVertex> queryVertices(String query, StringBuilder errMsg){
logger.error("before getGraph, " + errMsg.toString());
graph = getGraph(errMsg);
if (!errMsg.toString().equals("")){
return null;
}
logger.error("after getGraph, " + errMsg.toString());
Iterable<OrientVertex> vertices = null;
try {
OSQLSynchQuery<OrientVertex> qr = new OSQLSynchQuery<OrientVertex>(query);
vertices = graph.command(qr).execute();
logger.error("after graph command execute, " + errMsg.toString());
}
catch (Exception ex){
errMsg.append(ex.getMessage());
logger.error("graph command exception, " + errMsg.toString());
}
logger.error("before return vertices, " + errMsg.toString());
return vertices;
}
public List<ODocument> executeQuery(String sql, HashMap<String,Object> params,StringBuilder errMsg) {
List<ODocument> result = new ArrayList<ODocument>();
try {
db = getDatabase(errMsg);
if (!errMsg.toString().equals("")){
return null;
}
OSQLSynchQuery<ODocument> query = new OSQLSynchQuery<ODocument>(sql);
if (params.isEmpty()) {
result = db.command(query).execute();
} else {
result = db.command(query).execute(params);
}
} catch (Exception e) {
errMsg.append(e.getMessage());
//TODO: Add threaded error log saving mechanism
}
return result;
}
Due to index missing on table deadlock come, so check your all table which are involved in this operation and find out that indexes are present or not on column.
Refer link in which I have a same problem of deadlock.