JMS lookup inside thread fails - java

I have my client trying to lookup a JMS server. Here is my class JmsTest.java:
public static void main(String[] aInArgs)
{
boolean bContinue = true;
try
{
// determine JmsTest configuration based on command line arguments.
JmsTest jmsTest = parseCommandLine(aInArgs);
// connect to the server.
//jmsTest.initializeConnection();
Thread jmsFaultClientThread = null;
jmsFaultClientThread = new Thread("RUN") {
#Override
public void run() {
try
{
System.out.println("jmsFaultClient starting...");
jmsTest.initializeConnection();
}
catch (Exception e)
{
System.out.println("Exception: " + e.toString());
}
System.out.println("jmsFaultClient started.");
}
};
jmsFaultClientThread.start();
And my method initializeConnection():
public void initializeConnection() throws Exception
{
try
{
Hashtable env = new Hashtable();
env.put(Context.SECURITY_PRINCIPAL, user );
env.put(Context.SECURITY_CREDENTIALS, password);
jndiContext = new InitialContext(env);
System.out.println("Initializing Topic (" + strName + ")...");
try
{
topicConnectionFactory = (TopicConnectionFactory) jndiContext.lookup(CONNECTION_FACTORY);
}
catch (Exception e)
{
topicConnectionFactory = getExternalFactory(jndiContext);
}
When I run jmsTest.initializeConnection() like this everything works, and the lookup is working. However, the problem is when it's run inside the thread it gets stuck without any exception or any error. It's just stuck.
In my logs i'm seeing:
System.out.println("Initializing Topic (" + strName + ")...");
Which is a log inside my try / catch, and nothing else.
In dependencies, I have 2 jars, contening javax\jms. With the first one it's work inside the thread, and with the second one it doesn't. But I don't know why my jar can "block" the thread.
UPDATE 1 :
#AnotherJavaprogrammer said me to print the error:
here is my lookup with print :
try
{
getLogger().debug("TRY context");
Context lInitialContext = (Context) jndiContext.lookup(JMS_CONTEXT);
lInitialContext.lookup("SAMConnectionFactory");
getLogger().debug("END trying context");
}
catch (Exception e)
{
getLogger().debug("Catch");
getLogger().debug("Exception", e);
}
The output from getLogger().debug("END trying context") never comes, and I don't see the getLogger().debug("Catch") one either. So it appears I'm really "stuck" inside the lookup(). I can't go further, and it doesn't throw an exception.

Related

Java Oracle Database Change Notification issue with web application

I am using following code for registering and listening to Oracle database change notifications. This code is working fine when i run it as a standalone java program. It is receiving the notification from the database and printing as expected.
public class DBChangeNotification {
static final String USERNAME = "XXX";
static final String PASSWORD = "YYY";
static String URL = "jdbc:oracle:thin:#xxxx:xxxx:xxxx";
public static void main(String[] args) {
DBChangeNotification demo = new DBChangeNotification();
try {
demo.run();
} catch (SQLException mainSQLException) {
mainSQLException.printStackTrace();
}
}
public void run() throws SQLException {
OracleConnection conn = connect();
Properties prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS, "true");
prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION, "true");
prop.setProperty(OracleConnection.DCN_BEST_EFFORT, "true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try {
// add the listenerr:
DCNDemoListener list = new DCNDemoListener(this);
dcr.addListener(list);
// second step: add objects in the registration:
Statement stmt = conn.createStatement();
// associate the statement with the registration:
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("select * from xxxxxxxx where yyyy='zzzzz'");
while (rs.next()) {
}
String[] tableNames = dcr.getTables();
for (int i = 0; i < tableNames.length; i++) {
System.out.println(tableNames[i] + " is part of the registration.");
}
rs.close();
stmt.close();
} catch (SQLException ex) {
// if an exception occurs, we need to close the registration in order
// to interrupt the thread otherwise it will be hanging around.
if (conn != null) {
conn.unregisterDatabaseChangeNotification(dcr);
}
ex.printStackTrace();
throw ex;
} finally {
try {
// Note that we close the connection!
conn.close();
} catch (Exception innerex) {
innerex.printStackTrace();
}
}
}
/**
* Creates a connection the database.
*/
OracleConnection connect() throws SQLException {
OracleDriver dr = new OracleDriver();
Properties prop = new Properties();
prop.setProperty("user", DBChangeNotification.USERNAME);
prop.setProperty("password", DBChangeNotification.PASSWORD);
return (OracleConnection) dr.connect(DBChangeNotification.URL, prop);
}
}
/**
* DCN listener: it prints out the event details in stdout.
*/
class DCNDemoListener implements DatabaseChangeListener {
DBChangeNotification demo;
DCNDemoListener(DBChangeNotification dem) {
System.out.println("DCNDemoListener");
demo = dem;
}
#Override
public void onDatabaseChangeNotification(DatabaseChangeEvent e) {
Thread t = Thread.currentThread();
System.out.println("DCNDemoListener: got an event (" + this + " running on thread " + t + ")");
System.out.println(e.toString());
synchronized (demo) {
demo.notify();
}
}
}
My requirement is to use this feature in a web application. Web application when started in the server, has to listen to data change notifications (may be on a separate thread) and notify the application through a websocket client. I have added the following code in contextInitialized method of servlet context listener, so that it will start as soon as the application starts.
public class MyServletContextListener implements ServletContextListener {
DBChangeNotification demo;
#Override
public void contextDestroyed(ServletContextEvent arg0) {
//Notification that the servlet context is about to be shut down.
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
demo = new DBChangeNotification();
try {
demo.run();
} catch (SQLException mainSQLException) {
mainSQLException.printStackTrace();
}
}
}
I did not see any notifications received by the web application when database change event occurs in the registered table. Please help me in resolving the issue. I do not know whether this is a correct approach or not.... may please suggest any alternative except continuous polling. I need to start something in the server as soon as i receive notification from database. Thank you.
It might be that you're running your code on an Oracle instance that doesn't have the Notification API available.
Check this SO for more info

Change JVM Properties Using WebSphere MBeans

I'm trying to create a java program that will edit the class path properties of the JVM on WebSphere. I am now able to connect the program to the server and also find the node, but I don't know what to do next. Which MBean should I use to be able to find the JVM Classpath and configure it? I know I can edit it on the AdminConsole itself, but for this task, I would really have to do it using a Java Program.
I am also not allowed to use wsadmin and jacl/jython scripts.
Here is my code so far:
public class Expi
{
private AdminClient adminClient;
private ObjectName nodeAgent;
private AdminService adminSF;
String hostName = "localhost";
String hostPort = "8880";
String nodeName = "node1";
String servName = "server1";
public static void main(String [] args) throws NamingException, AdminException
{
Expi xp = new Expi();
xp.createAdminClient();
xp.getNodeAgentMBean(nodeName);
xp.testMB();
}
private void createAdminClient()
{
// Set properties for the connection
Properties connectProps = new Properties();
connectProps.setProperty(
AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
connectProps.setProperty(AdminClient.CONNECTOR_HOST, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_PORT, hostPort);
connectProps.setProperty(AdminClient.USERNAME, hostName);
connectProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "false");
// Connection Status Update
try
{
adminClient = AdminClientFactory.createAdminClient(connectProps);
System.out.println("Connected to SOAP Connection!");
}
catch (java.lang.Exception e)
{
System.out.println("Exception creating admin client: " + e);
System.exit(-1);
}
}
private void getNodeAgentMBean(String nodeName) throws NamingException
{
// Finding the specified node
try
{
String query = "WebSphere:type=Server,node="+ nodeName + ",*";
ObjectName queryName = new ObjectName(query);
Set s = adminClient.queryNames(queryName, null);
if (!s.isEmpty())
{
nodeAgent = (ObjectName)s.iterator().next();
System.out.println("Specified Node Found:" + nodeName);
}
else
{
System.out.println("Node agent MBean was not found");
System.exit(-1);
}
}
catch (MalformedObjectNameException e)
{
System.out.println(e);
System.exit(-1);
}
catch (java.lang.Exception e)
{
System.out.println(e);
System.exit(-1);
}
}
private void testMB() //find the correct MBean and use it to edit the values
{
AdminServiceFactory.getAdminService();
AdminServiceFactory.getMBeanFactory();
}
}
Any help would really be appreciated. Thank you!
You can execute the admin command using the AdminClient API. It is very difficult for to find out specific action since it is not well documented like JACL or JYTHON.
Sample available below for simple "listNodes" command. You can use the same approach to "listServers" and get the specific server object you want to modify. Once the server object is obtained, you can look at the same documentation below for executing command on specific target object.
AdminCommand cmd = cmdMgr.createCommand("listNodes");
cmd.setConfigSession(session);
AsyncCommandClient asyncCmdClientHelper =
new AsyncCommandClient(session, null);
asyncCmdClientHelper.execute(cmd);
CommandResult result = cmd.getCommandResult();
if (result.isSuccessful()) {
System.out.println("Successfully executed the command");
System.out.println("Result: ");
Object resultData = result.getResult();
if (resultData instanceof Object[]) {
Object[] resDataArr = (Object[])resultData;
for (Object resData : resDataArr) {
System.out.println(resData);
}
} else {
System.out.println(resultData);
}
} else {
System.out.println("Failed to execute the command");
result.getException().printStackTrace();
}
Documentation Link : https://www.ibm.com/developerworks/websphere/techjournal/1303_samantary/1303_samantary.html

How to handle authentication to MongoDB from Hibernate application

I need to catch errors during authentication (like wrong parameters). I find nothing about it. I have isolted the procedure with threads. But with this bad way, the user can't understand what goes wrong
Below, my code:
public static boolean access(String db, String ip, String usr, String pwd){
Map<String, String> persistenceMap = new HashMap<>();
persistenceMap.put("hibernate.ogm.datastore.database", db);
persistenceMap.put("hibernate.ogm.datastore.host", ip);
persistenceMap.put("hibernate.ogm.datastore.username", usr);
persistenceMap.put("hibernate.ogm.datastore.password", pwd);
Thread mainThread = Thread.currentThread();
Thread logThread = new Thread(() -> {
Connection.EMF = Persistence.createEntityManagerFactory("ogm-jpa-mongo", persistenceMap);
Connection.EM = Connection.EMF.createEntityManager();
Connection.isOpen = true;
});
Thread timeOut = new Thread( () -> {
try{ Thread.sleep( 5000 ); }
catch(InterruptedException ex){ }
mainThread.interrupt();
});
logThread.start();
timeOut.start();
try{ logThread.join(); }
catch(InterruptedException ex){ return false; }
Connection.TM = com.arjuna.ats.jta.TransactionManager.transactionManager();
return Connection.isOpen;
}
The problem is that when I insert worng parameters, it is thrown a MongoSecurityException. But i can't catch it, I can only read it on the monitor-thread. Any ideas?
I believe this is a result of the way your version of Hibernate catches the MongoSecurityException. I believe the MongoSecurityException is caught inside a nested try catch block.
The correct answer here is to update your Hibernate version to the latest release. However, if you would like to see that exception I think you can do the following.
String message = "";
try {
logThread.join();
} catch(Throwable e) {
throw e;
} catch(Exception e) {
message = e.getMessage();
}
If that doesn't work you might be able to chain as follows.
String message = "";
try {
logThread.join();
} catch(Throwable e) {
e.getCause();
e.getCause().getCause();
e.getCause()..getCause().getCause();
}

how to implement java future class to achieve parallelism to invoke a shell script for mutiple concurrent connections

I am using Java future class to achieve parallel programming. I am invoking shell script as shown below. I am invoking below function from my java controller
String NodeResult=restartNodes(HostName);
In controller implementation of future class
public static String restartNodes(final String hostName){
ExecutorService executor = Executors.newFixedThreadPool(threadNum);
List<FutureTask<Integer>> taskList = new ArrayList<FutureTask<Integer>>();
// Start thread for the first half of the numbers
FutureTask<Integer> futureTask_1 = new FutureTask<Integer>(new Callable<Integer>() {
#Override
public Integer call() throws Exception {
restartScript(hostName);
return SUCCESS;
}
});
taskList.add(futureTask_1);
executor.execute(futureTask_1);
return "successfully done";
}
code to invoke a script is:
public static void restartScript(String hostName) {
SSHExec ssh = null;
// Wrap the whole execution jobs into try-catch block
try {
// Initialize a ConnBean object, parameter list is ip, username,
// password
ConnBean cb = new ConnBean(IP_Add, User_Name,
Password);
ssh = SSHExec.getInstance(cb);
CustomTask ct2 = new ExecShellScript("/root/",
"./restartScript.sh",""+ hostName+"" );
// Connect to server
ssh.connect();
Result res = ssh.exec(ct2);
// Check result and print out messages.
if (res.isSuccess) {
System.out.println("Return code in success: " + res.rc);
System.out.println("sysout: " + res.sysout);
} else {
System.out.println("Return code: " + res.rc);
System.out.println("error message: " + res.error_msg);
}
} catch (TaskExecFailException ex) {
System.out.println(ex.getMessage());
ex.printStackTrace();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
} finally {
ssh.disconnect();
}
}
I am invoking multiple script and i want to them to be executed in parallel but while executing i am getting below error
com.jcraft.jsch.JSchException: session is down
at com.jcraft.jsch.Session.openChannel(Session.java:752)
at net.neoremind.sshxcute.core.SSHExec.exec(SSHExec.java:164)
at com.controller.UserLoginController.isNodeLive(UserLoginController.java:1620)
at com.controller.UserLoginController$3.call(UserLoginController.java:1724)
at com.controller.UserLoginController$3.call(UserLoginController.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Is their any max limit of getting ssh session i.e (concurrent session as i will be executing 5 scripts like this having different purpose and i want all of them will go in parallel.) if we use future class?

Java ExecutorService only running 2 threads not four

I am working on an application that retrieves files from different URL's.
There is a TreeSet that contains the target to download. This is processed in a loop with each item being called with an ExecutorService. Here's some code:
private void retrieveDataFiles() {
if (this.urlsToRetrieve.size() > 0) {
System.out.println("Target URLs to retrieve: " + this.urlsToRetrieve.size());
ExecutorService executorProcessUrls = Executors.newFixedThreadPool(this.urlsToRetrieve.size());//could use fixed pool based on size of urls to retrieve
for (Entry target : this.urlsToRetrieve.entrySet()) {
final String fileName = (String) target.getKey();
final String url = (String) target.getValue();
String localFile = localDirectory + File.separator + fileName;
System.out.println(localFile);
executorProcessUrls.submit(new WikiDumpRetriever(url, localFile));
dumpFiles.add(localFile);
//TODO: figure out why only 2 files download
}
executorProcessUrls.shutdown();
try {
executorProcessUrls.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException ex) {
System.out.println("retrieveDataFiles InterruptedException: " + ex.getMessage());
}
} else {
System.out.println("No target URL's were retrieved");
}
}
Then the WikiDumpRetriever:
private static class WikiDumpRetriever implements Runnable {
private String wikiUrl;
private String downloadTo;
public WikiDumpRetriever(String targetUrl, String localDirectory) {
this.downloadTo = localDirectory;
this.wikiUrl = targetUrl;
}
public void downloadFile() throws FileNotFoundException, IOException, URISyntaxException {
HTTPCommunicationGet httpGet = new HTTPCommunicationGet(wikiUrl, "");
httpGet.downloadFiles(downloadTo);
}
#Override
public void run() {
try {
downloadFile();
} catch (FileNotFoundException ex) {
System.out.println("WDR: FileNotFound " + ex.getMessage());
} catch (IOException ex) {
System.out.println("WDR: IOException " + ex.getMessage());
} catch (URISyntaxException ex) {
System.out.println("WDR: URISyntaxException " + ex.getMessage());
}
}
}
As you can see this is an inner class. The TreeSet contains:
Key : Value
enwiki-latest-pages-articles.xml.bz2 : http://dumps.wikimedia.org/enwiki/latest/enwiki-latest-pages-articles.xml.bz2
elwiki-latest-pages-articles.xml.bz2 : http://dumps.wikimedia.org/enwiki/latest/elwiki-latest-pages-articles.xml.bz2
zhwiki-latest-pages-articles.xml.bz2 : http://dumps.wikimedia.org/enwiki/latest/zhwiki-latest-pages-articles.xml.bz2
hewiki-latest-pages-articles.xml.bz2 : http://dumps.wikimedia.org/enwiki/latest/hewiki-latest-pages-articles.xml.bz2
The problem is that this process downloads 2 of the four files. I know that all four are available and I know that they can be downloaded. However, only 2 of them process at any time.
Can anyone shed any light on this for me please - what am I missing or what am I getting wrong?
Thanks
nathj07
Thanks to ppeterka - it was a limit from the source. So, to overcome this I set the fixed thread pool size to 2. This means that only 2 files are downloaded simultaneously.
The answer then was to find the vendor imposed limit and set the thread pool:
ExecutorService executorProcessUrls = Executors.newFixedThreadPool(2);
I wanted to accept an answer but couldn't seem to do it with the comments. Sorry if this was the wrong way to do it.
Thanks for all the pointers - the 'group think' really helped solve this for me.

Categories

Resources