Can't send any mail using JavaMail - java

I want to send a mail using Java but it doesn't work using this tutorial thai I found here http://www.tutorialspoint.com/java/java_sending_email.htm .
Here is my main method
public static void main(String[] args) {
// Recipient's email ID needs to be mentioned.
String to = "abcd#gmail.com";
// Sender's email ID needs to be mentioned
String from = "web#gmail.com";
// Assuming you are sending email from localhost
String host = "localhost";
// Get system properties
Properties properties = System.getProperties();
// Setup mail server
properties.setProperty("smtp.laposte.net", host);
// Get the default Session object.
Session session = Session.getDefaultInstance(properties);
try{
// Create a default MimeMessage object.
MimeMessage message = new MimeMessage(session);
// Set From: header field of the header.
message.setFrom(new InternetAddress(from));
// Set To: header field of the header.
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
// Set Subject: header field
message.setSubject("This is the Subject Line!");
// Now set the actual message
message.setText("This is actual message");
// Send message
Transport.send(message);
System.out.println("Sent message successfully....");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
And I have the error below:
javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25;
nested exception is:
java.net.ConnectException: Connection refused: connect
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1972)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:642)
at javax.mail.Service.connect(Service.java:295)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at javamail.JavaMail.main(JavaMail.java:58)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:319)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:233)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1938)
... 7 more
BUILD SUCCESSFUL (total time: 1 second)

error is in host use
host="smtp.gmail.com";
if you are using gmail id for sending mail. then you need to turn on gmail sending mail from extrnel application for users.
follow below link https://support.google.com/a/answer/57919?hl=en
turn on and then try again.

you can also use spring for sending mail.
bean.xml
<bean id="myMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="<user_name>" />
<property name="password" value="<password>" />
<!-- The name of the property, following JavaBean naming conventions -->
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
.
#Service("myMail")
public class myMailApi {
#Autowired
private MailSender myMailSender;
public void sendMail(String to,String from,String subject, String body){
SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
simpleMailMessage.setTo(to);
simpleMailMessage.setFrom(from);
simpleMailMessage.setSubject(subject);
simpleMailMessage.setText(body);
myMailSender.send(simpleMailMessage);
}
}
private static void sendMailClient() {
String mailXml = "mail-bean.xml";
ApplicationContext context = new ClassPathXmlApplicationContext(mailXml);
myMailApi mailBean = (mmyMailApi) context
.getBean("myMail");
mailBean.sendMail("<to>",
"<from>", "<subject>", "<body>");
}

With which server I can send email without have an account and login in java mail api ?
Is hotmail autorizing sending emails without logging in in java mail ?

Related

MyBatis hits Cannot Assign Requested Address Socket Exception at high volume with Pooled connection

I am using MyBatis to pull data from database into a cache as needed. At high volumes of message traffic, I start to see the following exception:
### Error querying database. Cause: org.postgresql.util.PSQLException: Connection to <my-database>:<my-port> refused. Check that the hostname and port are correct and that the postmaster is
accepting TCP/IP connections.
### The error may exist in mappers/<my-mapper>.xml
### The error may involve <my-mapper>.getById
### The error occurred while executing a query
### Cause: org.postgresql.util.PSQLException: Connection to <my-database>:<my-port> refused. Check that
the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:122)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:113)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectOne(DefaultSqlSession.java:73)
<truncated>
Caused by: org.postgresql.util.PSQLException: Connection to <my-database>:<my-port> refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:262)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:52)
at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:216)
at org.postgresql.Driver.makeConnection(Driver.java:404)
at org.postgresql.Driver.connect(Driver.java:272)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:208)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:201)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.doGetConnection(UnpooledDataSource.java:196)
at org.apache.ibatis.datasource.unpooled.UnpooledDataSource.getConnection(UnpooledDataSource.java:93)
at org.apache.ibatis.datasource.pooled.PooledDataSource.popConnection(PooledDataSource.java:385)
at org.apache.ibatis.datasource.pooled.PooledDataSource.getConnection(PooledDataSource.java:89)
at org.apache.ibatis.transaction.jdbc.JdbcTransaction.openConnection(JdbcTransaction.java:140)
at org.apache.ibatis.transaction.jdbc.JdbcTransaction.getConnection(JdbcTransaction.java:62)
at org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:315)
at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:75)
at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:61)
at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:303)
at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:154)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:102)
at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:82)
at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:120)
... 16 more
Caused by: java.net.ConnectException: Cannot assign requested address (connect failed)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.postgresql.core.PGStream.<init>(PGStream.java:61)
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:144)
... 37 more
I do not see these exceptions with small amounts of traffic, only at scale, so it doesn't seem to be any sort of functional problem or syntax issue with the mapper. In my config file for mybatis, this is how my source is configured:
<environments default = "ingestion_environment">
<environment id = "ingestion_environment">
<transactionManager type = "JDBC"/>
<dataSource type = "POOLED">
<property name = "driver" value = "org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql://<my-database>:<my-port>/<my-user>" />
<property name="username" value="<username>" />
<property name="password" value="<password>" />
<property name="poolMaximumCheckoutTime" value="50000"/>
<property name="poolMaximumActiveConnections" value="10"/>
</dataSource>
</environment>
</environments>
I'm trying to figure out what about high traffic could lead to these exceptions--with a pooled connection, it seems like the number of connections really shouldn't be changing even when there are more messages to handle. What could cause this?

Not sending scheduled reports by email with JasperReports Server

I'm dealing with an issue with JasperReports Server, i have it running in CentOS, i'm trying to schedule and send reports by email but still no success.
I just configured the js.quartz.properties file as follows:
report.scheduler.mail.sender.host=smtp.gmail.com
report.scheduler.mail.sender.username=myemailaddress#gmail.com
report.scheduler.mail.sender.password=Mypassword
report.scheduler.mail.sender.from=myemailaddress#gmail.com
report.scheduler.mail.sender.protocol=smtps
report.scheduler.mail.sender.port=465
report.scheduler.web.deployment.uri=http://etcetcetc.com:8080/jasperserver
also my applicationContext-report-scheduling.xml file:
<bean id="reportSchedulerMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${report.scheduler.mail.sender.host}"/>
<property name="username" value="${report.scheduler.mail.sender.username}"/>
<property name="password" value="${report.scheduler.mail.sender.password}"/>
<property name="protocol" value="${report.scheduler.mail.sender.protocol}"/>
<property name="port" value="${report.scheduler.mail.sender.port}"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtps.auth">true</prop>
<prop key="mail.smtps.starttls.enable">true</prop>
</props>
</property>
</bean>
I tried with ports 25, 465 and 587, disabling firewall, using smtp protocol instead of smtps and still i'm not able to accomplish this task, below you can see the error i'm gettins, i'll appreciate your help here.
No se completó la notificación de error de trabajo. Se produjo un error al enviarlo.
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465;
nested exception is:
java.net.ConnectException: Connection refused. Failed messages: javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465;
nested exception is:
java.net.ConnectException: Connection refused; message exception details (1) are:
Failed message 1:
javax.mail.MessagingException: Could not connect to SMTP host: smtp.gmail.com, port: 465;
nested exception is:
java.net.ConnectException: Connection refused
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1282)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:370)
at javax.mail.Service.connect(Service.java:275)
at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:389)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:340)
at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:336)
at com.jaspersoft.jasperserver.api.engine.scheduling.quartz.ReportExecutionJobMailNotificationImpl.sendMailNotification(ReportExecutionJobMailNotificationImpl.java:123)
at com.jaspersoft.jasperserver.api.engine.scheduling.quartz.ReportExecutionJob.sendMailNotification(ReportExecutionJob.java:942)
at com.jaspersoft.jasperserver.api.engine.scheduling.quartz.ReportExecutionJob.executeAndSendReport(ReportExecutionJob.java:538)
at com.jaspersoft.jasperserver.api.engine.scheduling.quartz.ReportExecutionJob.execute(ReportExecutionJob.java:219)
at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
at java.net.Socket.connect(Socket.java:525)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(SSLSocketImpl.java:550)
at com.sun.net.ssl.internal.ssl.BaseSSLSocketImpl.connect(BaseSSLSocketImpl.java:141)
at com.sun.mail.util.SocketFetcher.createSocket(SocketFetcher.java:232)
at com.sun.mail.util.SocketFetcher.getSocket(SocketFetcher.java:189)
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1250)

RabbitMQ invalid credentials with valid information

I'm working with some Java/Spring web applications and RabbitMQ.
I have App1 and App2 on the same tomcat server at the address 192.168.0.101.
They both communicate with a RabbitMQ server located at : 192.168.0.100.
App1 has this configuration in the spring context:
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"
destroy-method="destroy">
<property name="host" value="192.168.0.100" />
<property name="username" value="app" />
<property name="password" value="guest" />
<property name="virtualHost" value="/" />
</bean>
App2 has the same config except a different username, let's say:
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.CachingConnectionFactory"
destroy-method="destroy">
<property name="host" value="192.168.0.100" />
<property name="username" value="app2" />
<property name="password" value="guest" />
<property name="virtualHost" value="/" />
</bean>
The problem is that App1 can connect successfully to the RabbitMQ server, and App2 has always a invalid credentials error in the RabbitMQ logs.
Here is the permissions list for these users:
Listing permissions in vhost "/" ...
app .* .* .*
app2 .* .* .*
And here is what I get when I try to log in with the API (with both users): curl -i -u app:guest http://192.168.0.100:15672/api/whoami and curl -i -u app2:guest http://192.168.0.100:15672/api/whoami
HTTP/1.1 401 Unauthorized
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Date: Mon, 30 Jun 2014 14:58:37 GMT
Content-Length: 57
{"error":"not_authorised","reason":"Not management user"}
which seems pretty normal, I think, each user is recognized as valid user but not authorized for management. When I set the management tag for app2, I get this :
curl -i -u app2:guest http://192.168.0.100:15672/api/whoami
HTTP/1.1 200 OK
Server: MochiWeb/1.1 WebMachine/1.10.0 (never breaks eye contact)
Date: Mon, 30 Jun 2014 15:14:29 GMT
Content-Type: application/json
Content-Length: 80
Cache-Control: no-cache
{"name":"app2","tags":"management","auth_backend":"rabbit_auth_backend_internal"}
I know this is a lot of code but this is all I get, and I'm about to give up and never know what's going on. I really don't understand what I am doing wrong because configurations looks exactly the same.
What do you think ?
Thanks in advance ! A lot.
EDIT:
Here is the rabbitMq log line that I get when app2 tries to connect:
=ERROR REPORT==== 30-Jun-2014::16:42:38 ===
closing AMQP connection <0.1241.0> (192.168.0.101:52871 -> 192.168.0.100:5672):
{handshake_error,starting,0,
{amqp_error,access_refused,
"PLAIN login refused: user 'app2' - invalid credentials",
'connection.start_ok'}}
EDIT2:
And here is the Java error log that I get at the moment the app2 tries to connect:
Caused by: com.rabbitmq.client.PossibleAuthenticationFailureException: Possibly caused by authentication failure
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:355)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:516)
at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:545)
at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:181)
... 48 more
Caused by: com.rabbitmq.client.ShutdownSignalException: connection error; reason: java.net.SocketException: Connection reset
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:67)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:33)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:343)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:216)
at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:202)
at com.rabbitmq.client.impl.AMQConnection.start(AMQConnection.java:347)
... 51 more
Caused by: java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
...
Because time was against us I decided to uninstall and purge completely Tomcat from the server and do a fresh install then put each app one by one.
Guess what, they both connect successfully to RabbitMQ without any warning/error of any kind.
So, if anyone here know how a specific (external) tomcat configuration can prevent ONE app in particular from communicating with RabbitMQ you're welcome ...
By "external" I mean "not an app-related" configuration. I am not really a Tomcat expert, I know there is many files, and many ways to configure it, and I am still curious to know what happened.

Spring mail error while connecting to outlook.com smtp server

I am trying to send email through my outlook.com account (mapped to a specific domain, my email id would be like emailId#mydomain.com
I am getting the following exception.
2014-03-14 00:27:55,314 [pool-1-thread-1] ERROR
org.springframework.scheduling.support.MethodInvokingRunnable -
Invocation of method 'sendMail' on target class [class
com.sixthsense.lws.scheduler.TestMailSenderJob] failed
org.springframework.mail.MailSendException: Failed messages:
com.sun.mail.smtp.SMTPSendFailedException: 501 5.5.4 Invalid Email
address ; nested exception is:
com.sun.mail.smtp.SMTPSenderFailedException: 501 5.5.4 Invalid Email
address ; message exception details (1) are: Failed message 1:
com.sun.mail.smtp.SMTPSendFailedException: 501 5.5.4 Invalid Email
address ; nested exception is:
com.sun.mail.smtp.SMTPSenderFailedException: 501 5.5.4 Invalid Email
address
at
com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2108)
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1609)
at
com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1117)
at
org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:416)
at
org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:306)
at
org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:296)
at
com.sixthsense.lws.scheduler.TestMailSenderJob.sendMail(TestMailSenderJob.java:34)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
at
org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
at
org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
at
java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at
java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
at
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722) Caused by:
com.sun.mail.smtp.SMTPSenderFailedException: 501 5.5.4 Invalid Email
address
at com.sun.mail.smtp.SMTPTransport.mailFrom(SMTPTransport.java:1616)
... 20 more
My spring configuration are as below
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp-mail.outlook.com" />
<property name="port" value="587" />
<property name="username" value="userid#mydomian.com" />
<property name="password" value="password" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
</props>
</property>
</bean>
Following code sends the email
#Service
public class TestMailSenderJob {
#Autowired
JavaMailSender mailSender;
public JavaMailSender getMailSender() {
return mailSender;
}
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
#Scheduled(fixedDelay=5000)
public void sendMail()
{
System.out.println("############invoked sendMail");
SimpleMailMessage message = new SimpleMailMessage();
message.setTo("to#mailId.com");
message.setSubject("Test mail "+new Date().toString());
message.setText("test body");
getMailSender().send(message);
System.out.println("######### email send");
}
}
I am using oracle supplied jars for email version javamail-1.4.7 .
Edit: I am able to send receive emails in my outlook account(used for smtp in the program) through outlook web interface.
Fixed atlast, added from in message
message.setFrom("from#mailId.com");
I read in many places in the stacktrace this: "Invalid Email address". Please, check it in your code.
Another thing, for safety sake, please use the javax.mail-1.4.7 from maven repo.

Spring: Cannot connect to a JMX Server using RMI from behind a firewall

My Spring application is running on a machine that is behind a NAT firewall (pfSense). The machine's internal IP is a.b.c.d, and the NAT IP is w.x.y.z
The Spring configuration's serviceUrl is set to my internal IP (a.b.c.d) on port 1100, and when I start the application, I provide the following switches:
-Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
As shown above, I set -Djava.rmi.server.hostname=w.x.y.z in order to make it possible to connect to the application through the NAT. I have also opened up the relevant ports on the machine's firewall, and set up a port forward from w.x.y.z:1100 to a.b.c.d:1100
When I then try to connect to the app from outside the network using jconsole on w.x.y.z:1100, I get a java.io.IOException: jmxrmi
java.io.IOException: jmxrmi
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:236)
at sun.tools.jconsole.ProxyClient.<init>(ProxyClient.java:127)
at sun.tools.jconsole.ProxyClient.getProxyClient(ProxyClient.java:483)
at sun.tools.jconsole.JConsole$3.run(JConsole.java:524)
Caused by: java.rmi.NotBoundException: jmxrmi
at sun.rmi.registry.RegistryImpl.lookup(RegistryImpl.java:136)
at sun.rmi.registry.RegistryImpl_Skel.dispatch(Unknown Source)
at sun.rmi.server.UnicastServerRef.oldDispatch(UnicastServerRef.java:409)
at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:267)
at sun.rmi.transport.Transport$1.run(Transport.java:177)
at sun.rmi.transport.Transport$1.run(Transport.java:174)
at java.security.AccessController.doPrivileged(Native Method)
at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:556)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:811)
at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:670)
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)
at sun.rmi.transport.StreamRemoteCall.exceptionReceivedFromServer(StreamRemoteCall.java:275)
at sun.rmi.transport.StreamRemoteCall.executeCall(StreamRemoteCall.java:252)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:378)
at sun.rmi.registry.RegistryImpl_Stub.lookup(Unknown Source)
at sun.tools.jconsole.ProxyClient.checkSslConfig(ProxyClient.java:234)
If I try to connect using jconsole on w.x.y.z:1099, I get a java.rmi.ConnectException (Connection refused). How can I expose my JMX MBeans outside my NATted firewall?
java.rmi.ConnectException: Connection refused to host: w.x.y.z; nested exception is:
java.net.ConnectException: Operation timed out
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:129)
at javax.management.remote.rmi.RMIServerImpl_Stub.newClient(Unknown Source)
at javax.management.remote.rmi.RMIConnector.getConnection(RMIConnector.java:2373)
at javax.management.remote.rmi.RMIConnector.connect(RMIConnector.java:297)
at sun.tools.jconsole.ProxyClient.tryConnect(ProxyClient.java:355)
at sun.tools.jconsole.ProxyClient.connect(ProxyClient.java:313)
at sun.tools.jconsole.VMPanel$2.run(VMPanel.java:292)
Caused by: java.net.ConnectException: Operation timed out
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:208)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:147)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
... 9 more
Interestingly enough, I can connect to both ports (1099 and 1100) on w.x.y.z using telnet.
The relevant portion of my Spring configuration is:
<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<property name="port" value="1100" />
</bean>
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="registry">
<property name="server" ref="mbeanServer" />
<property name="objectName" value="connector:name=rmi" />
<property name="serviceUrl" value="service:jmx:rmi://a.b.c.d:1100/jndi/rmi://a.b.c.d:1100/server" />
<property name="environment">
<props>
<prop key="jmx.remote.jndi.rebind">true</prop>
</props>
</property>
</bean>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<!-- indicate to first look for a server -->
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
Note: I am not using any servlet containers.
EDIT: The first answer provided me with the basis for the solution to my specific problem, which can be seen in the second answer.
The initial port you define with com.sun.management.jmxremote.port is called a registry port and is only used to start negotiation and determine next port(s) to use for "real" communication. Java RMI mechanism uses dynamically allocated ports and in general is not compatible with firewalls.
What port is used by Java RMI connection?
That said, for JMX it is possible to work around it
a) Use system properties to lock both ports (requires Java 7)
com.sun.management.jmxremote.port
com.sun.management.jmxremote.rmi.port
b) Use custom code to request a specific port. See
JConsole over ssh local port forwarding
See also:
Why Java opens 3 ports when JMX is configured?
http://realjenius.com/2012/11/21/java7-jmx-tunneling-freedom/
Elaborating on the solution I identified using the links and pointers anttix gave me in his answer.
So, as mentioned in the answer above, using the system properties com.sun.management.jmxremote.port and com.sun.management.jmxremote.rmi.port is the basis for the solution.
I changed my Spring config to remove the registry and serverConnector beans, as this was not allowing me to register port 1099 (PermissionExceptions resulted in my being unable to bind to port 1099), and used the platform mbean server.
The Spring config I used was just this:
<bean id="mbeanServer" class="java.lang.management.ManagementFactory" factory-method="getPlatformMBeanServer"/>
Then, I started the application using the following switches:
-Dcom.sun.management.jmxremote -Djava.rmi.server.hostname=w.x.y.z -Dcom.sun.management.jmxremote.port=1099 -Dcom.sun.management.jmxremote.rmi.port=1099 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false
Setting the java.rmi.server.hostname to the NAT VIP w.x.y.z is critical as we need to be able to execute remote operations on locally created remote objects from outwith the network.
Note: This solution will only work on Java 7u4 or higher.

Categories