Dear All,
I would like to send email using java application. So I found this article http://www.javabeat.net/tips/33-sending-mail-from-java.html. The problem now my environment is linux with jdk1.6 I do know how to setup the Java Mail Api. Any guide please? Thank you.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
If you have 1.6 then you should have everything you need, regardless of OS platform.
Have a look at
http://www.javaworld.com/javaworld/jw-06-1999/jw-06-javamail.html
then look at the javamail documentation on Oracle's Java web site.
newbie14 0 Posting Pro
Dear James,
I saw one site it say just store the mail.jar in the ext library that will do the job for linux? I am confuse with the path and classpath what are they for exactly?
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
It's the classpath you need to concentrate on for jars. It's just a list of locations where Java can loook to find class definitions (*.class files). The locations can be directories/folders or .jar files.
Your .jar just needs to be anywhere that's mentioned in the classpath.
The standard install creates a lib/ext directory in the JRE directory. In Windows you can use this for any extra jars you need and Java will find them there. I believe that this is the same under Linux. Beware: if you are frequently messing about with your Java installs you may need to copy/move anything you have added to lib/ext every time you change the JRE installation. At the very least you will have to do this when Java 7 is released soon-ish. For some people this is a good reason not to use lib/ext (personally, I use lib/ext).
newbie14 0 Posting Pro
Dear James,
So what is your best advice as you also do use lib/ext? So can I manually just copy over there or set a classpath?
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
I would just stick it in lib/ext and worry about updates later. No need to deal with the classpath. This would not be as good idea for an app that was going to be installed & supported on a lot of machines however. Still, you can change your mind later.
newbie14 0 Posting Pro
Dear James,
Thank you for the confirmation. I got another question currently I have a socket programming reading data from multiple device and then I make a socket connection and proces it and insert into the db. Currently this is how I do below is my skeleton. First I make a connection then call a new thread and via the run function I do a lot of processing and storing into the db. So now based on certain criteria I will send email. So what is your suggestion do it in the run function or do a separate function? How will the splitting effect my multi thread?
public static void main(String[] args) {
try {
final ServerSocket serverSocketConn = new ServerSocket(9000);
while (true)
{
try
{
Socket socketConn1 = serverSocketConn.accept();
new Thread(new ConnectionHandler(socketConn1)).start(); }
catch(Exception e)
{
System.out.println("MyError:Socket Accepting has been caught in main loop."+e.toString());
e.printStackTrace(System.out);
}
}
}
catch (Exception e)
{
System.out.println("MyError:Socket Conn has been caught in main loop."+e.toString());
e.printStackTrace(System.out);
//System.exit(0);
}
}
class ConnectionHandler implements Runnable {
public void run() {
//read the data from the client & process it and store in the db.
}
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
If there's no further processing after sending the mail (ie that's simply just the last step of the process) then you could just call it from your ConnectionHandler. You'll probably need to synchronise the mail bit to avoid thread issues if two instances of ConnectionHandler are running simultaneously.
If the mail sending is more embedded than that, then I'd create a mail message object of some sort and stick it on a blocking FIFO job queue, with a single mail-sending thread processing requests off the queue one at a time. In real life I assume that any app will become more complex over time, so I'd probably go for this approach anyway.
Without a lot more detail of the overall requirements and volumes it's hard to be more specific.
newbie14 0 Posting Pro
Dear James,
MY environment is such that there are around nearly few thousand GPS device will be keep sending data to this Application it will process and check if it is in certain Geo Fence then send email. So I guess best to implement the synchronous thing but I am not too sure how to go about it can you give me some guidance.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
Yes, with those volumes I would queue the emails.
Here's a little class that allows you to add Runnable tasks to a work queue. It starts a background Thread to run them one at at time. It's NOT exactly what you need (you should probably queue emails, not tasks), but you;ll find the overall structure and concepts apply. For reasons I can't explain here it uses static methods, but normally you would create an instance of this class and use instance methods.
import java.util.concurrent.LinkedBlockingQueue;
import java.lang.Runnable;
public class BackgroundWorkQueue {
// enqueues tasks (Runnables) and executes them one at a time
// in a single new low-priority Thread
private static LinkedBlockingQueue<Runnable> queue = null;
private static queueProcessor processor;
private static boolean stopRequested = false;
public static void addTask(Runnable task) {
assert (!stopRequested) : "Task added to queue after stop() called";
if (processor == null) { // first time we've been called
queue = new LinkedBlockingQueue<Runnable>();
processor = new queueProcessor();
processor.setPriority(Thread.MIN_PRIORITY); // run in background
processor.start();
}
queue.add(task);
}
public static void stop() {
if (processor == null) return; // not running anyway
// stops thread as soon as queue is empty
stopRequested = true;
processor.interrupt();
}
private static class queueProcessor
extends Thread {
public void run() {
while ( ! (stopRequested && queue.isEmpty())) {
try {
queue.take().run();
yield(); // dont hog CPU on big batch of tasks
}
catch (InterruptedException ex) {
if ( (!stopRequested)) {
ex.printStackTrace(); // who interrupted us?
}
}
}
processor = null;
}
}
}
newbie14 0 Posting Pro
Dear James,
What is your opinion about my current code which calls each new thread when a new connection is made? So from my current run function I will call another function to determine whether to send email or not? So from that email function how can I queue. Can I just call a new instance of the BackgroundWorkQueue? So where will I put the codes to send the email in this BackgroundWork right? Actually why is this needed?
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
Starting a new Thread to handle each connection is standard practice. It allows you to accept connections while previous connections are still being processed.
Yes, call the email method from your run method after you have done the database processing etc.
If you are not comfortable with the whole queueing thing, maybe its best to set that aside for the moment; you can always come back to it later. For now just call the mail method(s) from your run. It will help if you split your email code into two methods - one to create the email method and a second to send it. (Call the second from the first, passing the email as a parameter). Declare the sending method as synchronised to avoid thread-related problems.
newbie14 0 Posting Pro
Dear James,
My current programme which accept the connection and process and store into the db some times run into "too many connection". Do you think I should opt for your queue method is it? I want to know and learn more about the queue and how it exactly work but for now I will follow your advice to get the basic to be ready and running first. Thank you very much.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
OK... with all those devices you must be getting a lot of connections and thus overrunning the connection limit. This will be much worse because you are holding the connection open while you do database accesses etc, and will get worse if you do the emails the same way.
With these kind of volumes your strategy should be to accept the connection, get the data, then close the connection at the earliest possible moment, ie before the database accesses and emailing. A simple .close(); on your connection socket should do it. Once you have closed the connection you can leave the database/email stuff to complete on the same thread without tying up the connection.
Ultimately this is another good reason to move to a queue - but with the database access AND the emails being queued by the connection handler. But like I said, this is something you can move on to after the easier version is working, if you just keep you code packaged in neat small methods.
Edited by JamesCherrill because: n/a
newbie14 0 Posting Pro
Dear James,
Below is my skeleton of my run function. So based on your idea the moment I have read the last character and see -1 I keep the string and immediately close via w.close(); then only I call another function to do the db n email processing. Please correct me.
public void run() {
Connection dbconn = null;
BufferedWriter w = null;
BufferedReader r = null;
try {
PrintStream out = System.out;
BufferedWriter fout = null;
w = new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream()));
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
int m = 0, count=0;
String line="";
String n="";
//w.write("$PA\n");
//w.flush();
while ((m=r.read()) != -1)
{
dbconn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?"+"user=******8&password=******");
stmt = dbconn.createStatement();
try
{
//select, insert and update statement here.
}
catch (SQLException ex)
{
System.out.println("MyError:Error SQL Exception : "+ex.toString());
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( stmt != null )
{
stmt.close();
}
else
{
System.out.println("MyError:stmt is null in finally close");
}
}
catch(SQLException ex){
System.out.println("MyError:SQLException has been caught for stmt close");
ex.printStackTrace(System.out);
}
try
{
if ( dbconn != null )
{
dbconn.close();
}
else
{
//logger.log(Level.SEVERE, "MyError:dbconn is null in finally close", "");
System.out.println("MyError:dbconn is null in finally close");
}
}
catch(SQLException ex){
System.out.println("MyError:SQLException has been caught for dbconn close");
ex.printStackTrace(System.out);
}
}
n="";
}
}
catch (IOException ex)
{
System.out.println("MyError:IOException has been caught in in the main first try");
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( w != null )
{
w.close();
}
else
{
System.out.println("MyError:w is null in finally close");
}
}
catch(IOException ex){
System.out.println("MyError:IOException has been caught in w in finally close");
ex.printStackTrace(System.out);
}
}
}
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
Looks like you do all the Database stuff in the input while loop before closing one of the streams? Can't tell because the code's not indented. If so, that's not going to help much. Also its receivedSocketConn1 that you need to close, if I read your code right. You create a new Database connection for every statement you perform? If so, that's going to kill performance.
It would help if you describe the input that you receive via the socket - how many lines is it?
ps. For your own benefit, please indent your code and keep it properly indented.
pps: I'm probably going to have to go offline soon, and probably won't be back until Friday, so don't worry if you suddenly stop getting replies. Time to fly solo?
newbie14 0 Posting Pro
Dear James,
Sorry for the codes not being indented earlier now I have done that. Ok let me explain what I do I read character by character then when I get this if (m==35) I will start build the whole string and strart processing. Then I open one db connection and link one statement with db connection. So via this single connection I will do a select, update and inserts too. Why I close just the w or the writer buffer because according to java documentation you close that it will hand the rest automatically. The input end of the day will be one string but I read charcter by charachter because I checked there is not \n so I can not use readline.
public void run()
{
Connection dbconn = null;
BufferedWriter w = null;
BufferedReader r = null;
try
{
PrintStream out = System.out;
BufferedWriter fout = null;
w = new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream()));
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
int m = 0,
count=0;
String line="";String n="";
while ((m=r.read()) != -1)
{
if (m==35)
{
n = n + (char) m;
dbconn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1?"+"user=******8&password=******");
stmt = dbconn.createStatement();
try
{
//select, insert and update statement here.
}
catch (SQLException ex)
{
System.out.println("MyError:Error SQL Exception : "+ex.toString());ex.printStackTrace(System.out);
}
finally
{
try
{
if ( stmt != null )
{
stmt.close();
}
else
{
System.out.println("MyError:stmt is null in finally close");
}
}
catch(SQLException ex)
{
System.out.println("MyError:SQLException has been caught for stmt close");
ex.printStackTrace(System.out);
}
try
{
if ( dbconn != null )
{
dbconn.close();
}
else
{
//logger.log(Level.SEVERE, "MyError:dbconn is null in finally close", "");
System.out.println("MyError:dbconn is null in finally close");
}
}
catch(SQLException ex)
{
System.out.println("MyError:SQLException has been caught for dbconn close"); ex.printStackTrace(System.out);
}
}
}//if m==35
}//end of while loop
}
catch (IOException ex)
{
System.out.println("MyError:IOException has been caught in in the main first try");
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( w != null )
{
w.close();
}
else
{
System.out.println("MyError:w is null in finally close");
}
}
catch(IOException ex){
System.out.println("MyError:IOException has been caught in w in finally close");
ex.printStackTrace(System.out);
}
}//end of final
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
That all looks fine, except that w.close() is still only executed after all the database stuff.
I don'r understand the reason for
while ((m=r.read()) != -1)
{
if (m==35)
{
n = n + (char) m;
Seems you read however many chars there are, but you only process anything after the 35th? And what is n? you add 35 to it because...?
Is the input always a 35 char message? Or maybe >1 such message?
newbie14 0 Posting Pro
Dear James,
I have tried like this where immediately after
if (m==35)
do this
w.close
the problem then I dont get complete data I loose a lot of other data. The if(m==35) is looking for # character. Thus once it found # it will process the string and that is why after the database processing I will clear the n="" which I forgot to show in my codes. So the loop wil have many sets of strings.
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
Let me check that I understand this correctly: Can you answer the following for me?
Each connection will send an unknown number of strings, delimited by # characters?
Each string will be 35 characters long?
How do you know if you have reached the last string?
Each string is processed separately for updating the database?
Your "too many connection" problem could be either too many TCP/IP connections OR too many database connections (you didn't specify which). Either way the solution involves the queue thing I talked about earlier.
Maybe you can just read those strings into a Java variable and put a copy onto a queue then close the TCP/IP connection. In another thread have a single database connection that just loops taking strings from the queue and processing them.
I strongly recommend you do a bit of reading on "producer/consumer" queue pattern, and have another look at the code I showed you (that queues runnables, not strings, but the principle is the same).
newbie14 0 Posting Pro
Dear James,
Below is my answers.
Each connection will send an unknown number of strings, delimited by # characters? Yes you are correct here.
Each string will be 35 characters long?
Not is not fixed to 35 characters but is delimited by#
How do you know if you have reached the last string?
We will check for the != -1 (null) that is why I tried to close immedialtely after reading the first # I tend to loose the rest of the sets of strings.
Each string is processed separately for updating the database?
Yes that is correct.
I agree with you I need some proper management on the huge data coming via tcp/ip and proper routing is needed.
Sorry in this case the "Too Many Connection" was due to db. Previously I had problem with File descriptor then I increase them is ok now.Below is the error from my log file.
MyError:stmt is null in finally close
MyError:dbconn is null in finally close
MyError:Error SQL Exception : com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
OK then, I would proceed like I said my previous post. Parse all the strings from the input stream and add them to a queue (LinkedBlockingQueue<String>). Develop and test the parsing by just writing the Strings to system.out before trying to go any further.
Then start a new thread that opens one DB connection then loops taking the Strings from the queue and processing them one at a time. (If the queue is empty the take() method will just wait until a String is added.)
Advantages:
It breaks one big problem into two smaller problems.
You can close and re-use the TCP/IP connection very quickly because you are just parsing the data.
You only have one Db connection to open so overhead is minimal.
Database transactions are processed one at a time in one thread, so no threading problems.
LinkedBlockingQueues are thread-safe so you can add Strings from multiple threads and process them in another thread without any threading problems.
You are using the "producer/consumer" pattern, which is a well known good solution.
newbie14 0 Posting Pro
Dear James,
I agree with your idea. Infact I also have done some reading on my own now on producer and consumer. I really can not find a very basic example for me to understand it well and try to apply into my scenario. Remember about the email function you were tell me to put a synchronize keyword for now is it ?
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
I posted you a very simple example earlier - have a look at that again. The concept is
You have a queue - its just a list of items, Strings in your case, Runnables in mine.
It has an add method that you use to add new items onto the end of the queue
It has a take method that another thread can use to get the oldest item from the queue for processing. If the queue is empty take just waits until someone adds a new item, then takes it.
The rest of my sample code is just about shutting down the queue in a tidy way when the app is finished - ignore that until you understand the basics.
If you use the queue with a single consumer thread then there;s no need to worry about synchronising anything
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
Hello again. Here's the most basic example I could come up with. It's fully runnable as it is.
import java.util.concurrent.LinkedBlockingQueue;
public class Demo {
public static void main(String[] args) {
new Demo();
}
private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Demo() {
new Thread(new QueueProcessor()).start(); // processor is now waiting for data...
queue.add("hello"); // so let's give it some
queue.add("world");
queue.add("Please shut down now"); // tell processor to shutdown
}
class QueueProcessor implements Runnable {
@Override
public void run() {
while (true) {
try {
String data = queue.take();
if (data.equals("Please shut down now")) {
System.out.println("QueueProcessor is shutting down");
break; // exit while loop, ends run() method
}
System.out.println("Processing " + data);
// this is where you process each string of data
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
newbie14 0 Posting Pro
Dear James,
Really appreciate you I do not know how to thank you. Give me some time to test and really try to understand it in depth first the basic codes.Thank you once again.
newbie14 0 Posting Pro
Dear James,
Ok I can get the idea now better. I still cant get it what is the advantage of using let say compare to a for loop etc. So in my case is this how I should do it. Every read of the complete string put on queue. So at the take I will take the string and process (insert into db,send email etc). Correct me if I am wrong.
new Thread(new QueueProcessor()).start();
while ((m=r.read()) != -1) {
read a string complete add to the queue
JamesCherrill 4,733 Most Valuable Poster Team Colleague Featured Poster
That look good.
Advantages:
Right now you hold a TCP/IP connection open while you do a database update on the same thread. You get lots of TCP/IP connections, so some/many threads executing simultaneously. You run out of TCP/IP connections because each one is taking so long. You run out of database connections because so many can happen at the same time. Your program is complex because everything happens in the same method.
Use a queue and:
You only hold each TCP/IP connection open for as long as it takes to extract the Strings.
You have just one database connection that processes each update one at a time.
You separate the TCP/IP code from the database code, splitting one big problem into two small problems.
Also everything I said about the database updates also applies to the email part.
I have to go now, back tomorrow.
ravi063 0 Newbie Poster
Hi,
U can send mail using java mail api.. First download api jar from the site:
http://www.oracle.com/technetwork/java/javamail/index-138643.html
U must include the jar file in your build path, indeed if u have editor like NetBeans or Eclipse u can add the jar file to the lib.
Check the code in ur link:
props.put("mail.smtp.host", "smtp.gmail.com");--> Here they are using email server of Gmail. U can use email server of your internet service provider also.
props.put("mail.smtp.port", "465"); --> This is the port no on Gmail Server at which the SMTP server is running
Let me know if u have any doubts...
newbie14 0 Posting Pro
Dear James,
I have tried something like below.I get this error commServer.java:66: illegal start of expression
private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
Where exactly should I put this statement?
class ConnectionHandler implements Runnable {
private Socket receivedSocketConn1;
DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy");
DateFormat inDf=new SimpleDateFormat("ddMMyyHHmmss");
DateFormat outDf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ConnectionHandler(Socket receivedSocketConn1) {
this.receivedSocketConn1=receivedSocketConn1;
}
//@Override
public void run()
{
private LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>();
BufferedWriter w = null;
BufferedReader r = null;
String n="";
try {
PrintStream out = System.out;
BufferedWriter fout = null;
w = new BufferedWriter(new OutputStreamWriter(receivedSocketConn1.getOutputStream()));
r = new BufferedReader(new InputStreamReader(receivedSocketConn1.getInputStream()));
int m = 0, count=0;
String line="";
while ((m=r.read()) != -1)
{
n = n + (char) m;
//n = n + (char) m;
// n = new StringBuffer().append((char)m).toString();
int i = n.indexOf("GET");
if(i != -1) {
break;
}
//System.out.println("\njoinig the N : "+n);
//System.out.println("\nM : "+m);
if (m==35)
{
w.write("$PA\r\n");
w.flush();
//processDB(n);
queue.add(n);
n="";
}
}
}
catch (IOException ex)
{
System.out.println("MyError:IOException has been caught in in the main first try");
ex.printStackTrace(System.out);
}
finally
{
try
{
if ( w != null )
{
w.close();
}
else
{
System.out.println("MyError:w is null in finally close");
}
}
catch(IOException ex){
System.out.println("MyError:IOException has been caught in w in finally close");
ex.printStackTrace(System.out);
}
}
}
class QueueProcessor implements Runnable {
@Override
public void run() {
while (true) {
try {
String data = queue.take();
if (data.equals("Please shut down now")) {
System.out.println("QueueProcessor is shutting down");
break; // exit while loop, ends run() method
}
System.out.println("Processing " + data);
// this is where you process each string of data
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.