How to send email as a independent code for faster response? - java

On click of a submit button , i am calling a Jersey REST Web-service which is responsible to
1 .Insert record in the database
2.And send email .
This is my code
if (operation.equals("Insert")) {
String SQLInsertMgmtUser = "INSERT INTO User (depotID , emp_ID , appUserName)VALUES(? , ? , ?)";
String sendEmail = SendEmailUtility.sendmail(empmail, generatedPwd_str);
}
public static String sendmail(String sendemalto,String generatedpwd) throws IOException
{
String result = "fail";
Properties props_load = getProperties();
try {
// Code to send the email Using java mail API
result = "success";
} catch (MessagingException e) {
result = "fail";
logger.error("Exception Occured"+ "sendemalto" +sendemalto , e);
}
return result;
}
public static Properties getProperties()
{
if (props == null) {
File configDir = new File(System.getProperty("catalina.base"), "conf");
File configFile = new File(configDir, "email.properties");
InputStream stream = null;
try {
stream = new FileInputStream(configFile);
} catch (FileNotFoundException e) {
logger.error("exception" , e);
}
props = new Properties();
try {
props.load(stream);
} catch (IOException e) {
logger.error("exception" , e);
}
}
return props;
}
This code works fine , but the issue i am facing with this code is that the Submit Operation is nearly taking 15 seconds .
My question is that , is it possible to run the send email code as a independent thread .
Please share your views as how to approach this requirement .

Simplest way to execute a task asynchronously is by using an ExecutorService.
Something like this:
public YourClass {
private ExecutorService executorService = Executors.newFixedThreadPool(10);
public void yourMethod() {
if (operation.equals("Insert")) {
String SQLInsertMgmtUser = "INSERT INTO User (depotID , emp_ID , appUserName)VALUES(? , ? , ?)";
executorService.execute(new Runnable() {
public void run() {
SendEmailUtility.sendmail(empmail, generatedPwd_str);
}
});
}
}

I would setup a localhost MTA (like OpenSMTPD) which then relays to your real MTA ("Satellite Mode"). This gives you a local queue. If it takes a few seconds to send the message to your remote MTA, that's okay as the local MTA will handle that.
This also has the advantage of centralized configuration if you want to share the MTA among multiple applications.

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

Why java socket.io emit is fail

i'm creating android application with Socket.io and node.js server.
My js server:
var http = require('http');
var server = http.createServer(function(req, res) {
});
var mysql = require('mysql');
var db = mysql.createConnection({
host:,
port:,
user:,
password:,
database:
});
var resultconnection = "";
db.connect(function(err){
if (err) {
resultconnection = err;
}
});
var io = require('socket.io').listen(server);
io.on('connection',function(socket){
console.log('Connected!');
socket.on("createaccount", function(data){
console.log('Create account executed.');
if(resultconnection != ""){
db.query("INSERT INTO USER (USERNAME, PASSWORD, EMAIL, BIRTHDATE) VALUES('"+data["username"]+"', SHA1('"+data["password"]+"'), '"+data["email"]+"', "+data["birthdate"]+"')");
resultconnection = "OK";
}
socket.emit('response', {"response": resultconnection});
});
});
server.listen(8080);
Android client(java):
try {
socket = IO.socket("http://localhost:8080");
socket.on("response", new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONObject obj = (JSONObject) args[0];
try {
result = obj.getString("message");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
socket.connect();
JSONObject createUser = new JSONObject();
try {
createUser.put("username", username);
createUser.put("password", password);
createUser.put("email", email);
createUser.put("birthdate", datanasc);
} catch (JSONException e) {
e.printStackTrace();
}
socket.emit("createaccount", "");
} catch (URISyntaxException e) {
result = e.getMessage();
}
Console.log("Connected") is running but when I run the socket.emit("createaccount") the client does not run on the server.
I think the server IP you gave in the client code is not correct. It is trying to connect to the localhost of your Android device while your server is running on some other remote system.
Try changing the server IP in the following snippet(ideally this should be something other than localhost):
try {
socket = IO.socket("<server_IP:server_PORT");
socket.on("response", new Emitter.Listener() {
#Override
public void call(Object... args) {
JSONObject obj = (JSONObject) args[0];
try {
result = obj.getString("message");
} catch (JSONException e) {
e.printStackTrace();
}
}
});
socket.connect();
JSONObject createUser = new JSONObject();
try {
createUser.put("username", username);
createUser.put("password", password);
createUser.put("email", email);
createUser.put("birthdate", datanasc);
} catch (JSONException e) {
e.printStackTrace();
}
socket.emit("createaccount", "");
} catch (URISyntaxException e) {
result = e.getMessage();
}
There are significant structural problems with how your server is designed:
You're trying to save resultconnection in a module global. That means you can only ever have one socket.io client connection that will work properly. The second connection will see the resultconnection from the previous client connection. There's just no way this is a proper way to do things. It could possibly work if you never ever had more than one client connect to your server - not just one client at a time, but one client all time.
The way you handle the async database operation in the createaccount message handler is just wrong. You are trying to .emit() the resultconnection back to the client before it has been set.
Your error handling for the db.connect() call does not seem correct. When you can't connect to the database you need to take some action, not just set a variable as such and proceed on as if nothing is wrong. Even that variable you set is being used wrong later. You're checking to see if you had an error on the connect and if you did, then you're trying to do a database operation. Besides just a messed up design, this logic is even backwards.
To think about how to fix the first issue, you need to explain what you're trying to do with this statement:
if(resultconnection != ""){
because that will need to be done a different way. You can't just save global state in your server and expect that to represent the state of any incoming connection.
How to fix the second issue will depend upon what is done for the first issue.
How to fix the third issue involves some design decisions about what to do with your server when you can't connect to the database (shut-down, retry, log, etc...).

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?

Program in Jade Running on Netbeans not Transferring Message

I have created an agent which accepts a value and then passes a message on to the next agent. I am having problem with entering a value and so my message is also not being transfered. Here is my Agent class, below. Does anyone know what I can do to fix it?
public class Prgm extends Agent {
int val;
protected void setup() {
Objects[] args = getArguments();
if (args!=null && args.length > 0)
val = Integer.parseInt((String) args[0]);
addBehaviour(new OneShotBehaviour(this) {
public void action() {
if (val == 1) {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.setLanguage("english");
msg.SetOntology("DG Status");
msg.SetContent("DG connected");
msg.addReceiver(new AID("r1", AID.ISLOCALNAME));
myAgent.send(msg);
} else {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(new AID("r1", AID.ISLOCALNAME));
msg.setLanguage("english");
msg.setOntology("DG Status");
msg.setContent("DG not connected");
send(msg);
}
}
});
}
If you don't need to use ontologies right away don't. For strings you can use:
ACLmessage.setContent("string message") and String stringmsg=ACLmessage.getContent()
If you need something more try Java serialization, it's way simpler than using ontologies.
Also I don't think this line is acceptable. new AID("r1", AID.ISLOCALNAME). One would typically contact the df (directory facilitator) agent querying available agents or services. Try something like this
DFAgentDescription template = new DFAgentDescription();
ServiceDescription sd= new ServiceDescription();
sd.setType(Service);
sd.setName(agentName);
template.addServices(sd);
try {
DFAgentDescription[] result = DFService.search(this, template);
listAgents.clear();
for(int i = 0; i<result.length;++i)
{
listAgents.addElement(result[i].getName());
}
//System.out.println(listAgents);
} catch (FIPAException e) {
// TODO Auto-generated catch block
e.printStackTrace();
log(this.getAID() +"!!error in requesting service ="+Service);
}
return (AID) listAgents.get(0);

Create new thread in for loop inside public void method()

I have a class that ping IP addresses. To start ping I have public vod run() method to start pinging. Problem is that I want ping more IP addresses at same time (for each IP address I need new Thread). So how can I create new Thread inside for loop. Here is code of my ping class:
public void run()
{
if (dbConnection.ConnectToDB())
{
for (;GateWayKey<=GateWayKeyStop;GateWayKey++)
{
if(stop || this.isInterrupted()){
return;
}
ip="192.168."+GateWayKey+".1";
InetAddress address;
try {
address = InetAddress.getByName(ip);
try {
if (address.isReachable(PingTime))
{
//System.out.println("Pronaden GateWay: "+ip)
// labele.IP
sql="INSERT INTO `iptables` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ip+"', '"+address.getHostName().toString()+"', '"+GateWayKey+"');";
framedocs.WriteMonitorData (ip, address.getHostName().toString(),"2000","DA",dbConnection.WriteToDB(sql));
for (;SubNetKey<=SubNetKeyStop;SubNetKey++)
{
if(stop || this.isInterrupted()){
return;
}
InetAddress addressIps = InetAddress.getByName("192.168."+GateWayKey+"."+SubNetKey);
System.out.println("Provjeravam IP: "+addressIps);
if (addressIps.isReachable(PingTime))
{
ip="192.168."+GateWayKey+"."+SubNetKey;
System.out.println("Pronaden IP: "+ip);
sql="INSERT INTO `iptables` (`IP` , `COMPUTER_NAME` , `GATEWAY_KEY`) VALUES ('"+ip+"', '"+addressIps.getHostName().toString()+"', '"+GateWayKey+"');";
framedocs.WriteMonitorData (ip, address.getHostName().toString(),"2000","DA",dbConnection.WriteToDB(sql));
}
else
{
framedocs.WriteMonitorData (addressIps.toString(), "N/A","2000","NE","N/A");
}
}
}
else
{
framedocs.WriteMonitorData (ip, "N/A","2000","NE","N/A");
}
} catch (IOException e) {
// TODO Auto-generated catch block
framedocs.WriteMonitorData (ip, "N/A","2000",e.getMessage(),"N/A");
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
;
framedocs.WriteMonitorData (ip, "N/A","2000",e.getMessage(),"N/A");
}
}
}
else
{
framedocs.WriteMonitorData ("MySQL error", "N/A","N/A","N/A","N/A");
}
}
A general way to do these kinds of tasks is, first, create a class to hold the results you want to get from each thread:
final class PingResult {
public String ip;
public String hostname;
//... other things you want go here
}
Then create a callable that does the actual work
class PingTask extends Callable<PingResult>{
private final String gateWayKey, subNetKey;
//... other parameters you need go here
public Ping( String gwKey, String snKey /*+ others? */ ){
// This is just a way to pass parameters to your pinging function
this.gateWayKey = gwKey;
this.subNetKey = snKey;
// ...
}
public PingResult call(){
// Do actual pinging work here
if ( /* Success */ )
{
PingResult result = new PingResult();
result.ip= /*Fill these in*/;
result.hostname = /* ... */;
return result;
}
// Otherwise we failed, I'm using null as a failure sentinel
// (you can come up with something better)
return null;
}
}
Then in your calling code, set up a thread pool, cue up the requests, and then process the results.
// Might need to tweak the # for best performance
final int NUM_THREADS = Runtime.getRuntime.availableProcesses();
ExecutorService exec = Executors.newFixedThreadPool( NUM_THREADS );
List<Future<PingResult>> results = new ArrayList<PingResult>();
for(/* ... */){
results.add( exec.submit( new PingTask( gateway, subnet ) ) );
}
for( Future<PingResult> future : results ){
PingResult result = future.get();
// Process the result here (this is where you insert into the DB)
}
exec.shutdown(); // VERY IMPORTANT. If you don't do this the JVM will never stop.
create a new class inside your main class and do your operations in that inner class
every-time you need to create a new thread just initiate a new instance of that inner class and call its methods created for this purpose
If you find this answer not useful check my other answer on multi-threading.

Categories

Resources