Programmatically enabling remote jmx monitoring - java

I am attempting to enable my core java application for remote accessibility via JMX.
However, two restrictions are making it harder than it should be.
a) I am not at the liberty to change the script which starts the app on the linux box. Therefore, I cannot pass any of the "jmxremote" parameters to the jvm.
b) It is very possible that the remote port ( com.sun.management.jmxremote.port = xxxx ) I specify is not open and I cannot modify the script to try another open port. I must do it automatically.
I tried to get around these restrictions by writing a class with would set all the required jmxremote params as well as find a "free" port.
public class JmxRemoteConnectionHelper{
#Override
public void init( ) throws Exception{
InetAddress address = InetAddress.getLocalHost();
String ipAddress = address.getHostAddress();
String hostname = address.getHostName();
String port = String.valueOf( getFreePort( ) );
System.setProperty("java.rmi.server.hostname", ipAddress );
System.setProperty("com.sun.management.jmxremote", "true" );
System.setProperty("com.sun.management.jmxremote.authenticate", "false" );
System.setProperty("com.sun.management.jmxremote.ssl", "false" );
System.setProperty("com.sun.management.jmxremote.port", port );
}
private final int getFreePort( ){
**//seedPort is passed in the constructor**
int freePort = seedPort;
ServerSocket sSocket = null;
for( int i=ZERO; i<PORT_SCAN_COUNTER; i++ ){
try{
freePort = freePort + i;
sSocket = new ServerSocket( freePort );
//FOUND a free port.
break;
}catch( Exception e ){
//Log
}finally{
if( sSocket != null ){
try{
sSocket.close();
sSocket = null;
}catch(Exception e ){
//Log
}
}
}
}
return freePort;
}
}
As shown below, I, then initialize it via spring.
<bean id="JmxRemoteConnection" class="JmxRemoteConnectionHelper" init-method="init" />
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean" depends-on="JmxRemoteConnection" />
<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false" >
<property name="assembler" ref="assembler"/>
<property name="namingStrategy" ref="namingStrategy"/>
<property name="autodetect" value="true"/>
<property name="server" ref="mbeanServer"/>
</bean>
<bean id="jmxAttributeSource" class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<bean id="assembler" class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
<bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy" lazy-init="true">
<property name="attributeSource" ref="jmxAttributeSource"/>
</bean>
To test, I start the app on my windows machine. It starts up correctly. However, when I bring up JConsole on the same box and try to connect via "remote process" (ip:port), I get a "connection refused" message at the bottom.
My suspicion is that the JMX agent is not seeing any of the remote system properties that I am setting.
I am using JDK 1.6.

Since you are already using Spring I think you should see if using a ConnectorServerFactoryBean can do what you are looking to do. I've never had to start a remote JMX server but it looks like that's what that object can do for you.

See the answers to this for enabling jmx within the process:
Is it possible to enable remote jmx monitoring programmatically?
To find a free port simply wrap LocateRegistry.createRegistry() in a loop which retries with a new port number until it succeeds.
Of course you'll have to communicate the final port number to whatever needs to connect. Alternatively running jstatd on the host should make it discoverable

Related

How to establish a FTPS data connection to a FileZilla Server 1.2.0

It is a known problem to use the Java FTPSClient of Apache commons-net with session resumption. Session resumption is a security feature which a FTPS server can require for data connections. The Apache FTPSClient does not support session resumption, and the JDK APIs make it hard to build a custom implementation. There are a couple of workarounds using reflection, see e.g. this answer and this commons-net bug entry.
I use such a workaround (see snipped below) in JDK 11 and tested it against a local FileZilla Server. It works with FileZilla Server 0.9.6, but it doesn't with FileZilla Server 1.2.0, which is the latest version at the time of writing. With that version, when trying to establish a data connection, the server responds with:
425 Unable to build data connection: TLS session of data connection not resumed.
As I said, FileZilla Server 0.9.6 is fine with how I do session resumption, and I made sure that the setting for requiring session resumption is activated.
In FileZilla Server 1.2.0, such settings are now set implicitly and cannot be changed via the GUI, maybe not at all. Are there some server settings that I can tweak for this to work? Or is it an issue with how I implemented the workaround? Does anyone experience similar issues?
This is the workaround I am using:
public class FTPSClientWithSessionResumption extends FTPSClient {
static {
System.setProperty("jdk.tls.useExtendedMasterSecret", "false");
System.setProperty("jdk.tls.client.enableSessionTicketExtension", "false");
}
#Override
protected void _connectAction_() throws IOException {
super._connectAction_();
execPBSZ(0);
execPROT("P");
}
#Override
protected void _prepareDataSocket_(Socket socket) throws IOException {
if (useSessionResumption && socket instanceof SSLSocket) {
// Control socket is SSL
final SSLSession session = ((SSLSocket)_socket_).getSession();
if (session.isValid()) {
final SSLSessionContext context = session.getSessionContext();
try {
final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
sessionHostPortCache.setAccessible(true);
final Object cache = sessionHostPortCache.get(context);
final Method putMethod = cache.getClass().getDeclaredMethod("put", Object.class, Object.class);
putMethod.setAccessible(true);
Method getHostMethod;
try {
getHostMethod = socket.getClass().getMethod("getPeerHost");
}
catch (NoSuchMethodException e) {
// Running in IKVM
getHostMethod = socket.getClass().getDeclaredMethod("getHost");
}
getHostMethod.setAccessible(true);
Object peerHost = getHostMethod.invoke(socket);
InetAddress iAddr = socket.getInetAddress();
int port = socket.getPort();
putMethod.invoke(cache, String.format("%s:%s", peerHost, port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostName(), port).toLowerCase(Locale.ROOT), session);
putMethod.invoke(cache, String.format("%s:%s", iAddr.getHostAddress(), port).toLowerCase(Locale.ROOT), session);
}
catch (Exception e) {
throw new IOException(e);
}
}
else {
throw new IOException("Invalid SSL Session");
}
}
}
}
The address under which the socket is cached is determined using getPeerHost, getInetAddress().getHostName(), and getInetAddress().getHostAddress(). I tried several combinations of doing or not doing these three, but I always get the same result.
Edit:
Here is a screenshot of the server logs of the full session:
As stated in this StackOverflow post it is possible to tell the JVM that only TLS 1.2 should be used.
Here is the link to the original answer which worked for me: command for java to use TLS1.2 only
You have to add a command line parameter at the start of the JVM in this case this is: java -Djdk.tls.client.protocols=TLSv1.2 -jar ... <rest of command line here>
This simple parameter worked for me, now I can connect and transfer data from a FTP-Server wich runs FileZilla FTP-Server 1.3.0

Spring Java Mail - How to know send mail be read, bounce or forward by receiver?

I'm new on spring and java mail, may i know how the email send by java mail is read, bounce or forward. I used google search only found the way how to send a mail. Anyone know where can get the reference on it or provide me some example on it?
Thank you.
Below is my code send mail with spring java mail:
Spring-Mail.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com" />
<property name="port" value="587" />
<property name="username" value="xxxxxxxx#gmail.com" />
<property name="password" value="xxxxxx" />
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.smtp.from">xxxxxxxx#hotmail.com</prop>
</props>
</property>
</bean>
<bean id="mailMail" class="com.penril.my.MailMail">
<property name="mailSender" ref="mailSender" />
</bean>
</beans>
MailMail.java
public class MailMail
{
private JavaMailSender mailSender;
public void setMailSender(JavaMailSender mailSender) {
this.mailSender = mailSender;
}
public void sendMail(String from, String to, String subject, String msg) {
MimeMessage message = mailSender.createMimeMessage();
try {
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setFrom(from);
helper.setTo(to);
helper.setSubject(subject);
helper.setText(msg);
mailSender.send(message);
} catch (MessagingException e) {
throw new MailParseException(e);
}
}
}
MainClass.java
public class MainClass
{
public static void main( String[] args )
{
ApplicationContext context =
new ClassPathXmlApplicationContext("Spring-Mail.xml");
MailMail mm = (MailMail) context.getBean("mailMail");
mm.sendMail("xxx123xxx#gmail.com",
"xxx234xxx#hotmail.co1m",
"Testing123",
"Testing only \n\n Hello Spring Email Sender");
}
}
There is no standard way of doing this that's accepted and honored across the board. I see that you have some options, though:
Add a header "Return-Receipt-To" with your e-mail address in the value. If the recipient of the e-mail has a client which honors this header, then a return receipt will be sent to you when the e-mail is opened. This is not reliable, mind you, as the user can always decide not to send the receipt, even if he has a client that supports it.
Add an image into your e-mail that loads from your server and put a parameter on the image that includes the user's e-mail address. When the e-mail loads, the image will load from your server. Write a script that collects the e-mail parameter and then delivers a blank image. This is also not reliable, however, as many mail clients prompt users if they wish to download images and they can always choose not to. Also, some (mostly older) e-mail clients do not support images.
Perhaps the most reliable way is not to include the message in your e-mail at all. Include only a link to a website where the message can be read, and include their e-mail address or a unique code in the link. This way, you know exactly who read the message. Of course, this has the downside that people aren't actually getting the message in their inbox, and they also may choose not to go to the website to read it.
Ultimately, I think you're going to have to come up with a creative solution to solve this problem, unless you're happy getting spotty results.
Sign up for a free account for a Cloud Based SMTP service, for example Sendgrid, which will save you the trouble of manually implementing what was suggested in the previous answer.
https://sendgrid.com/
You can send 400 emails a day on the free tier. You can manually check the status of individual messages 'opened', 'bounced' etc using the management console or there are various APIs available to do this programatically (although some are only available on paid tiers).
For example their WebHooks API will call back your server when an event (opened, bounced, click etc.) occurs:
https://sendgrid.com/docs/API_Reference/Webhooks/event.html

Hiveserver2 not responding

I have a hiveserver(hiveserver2) running on port 10000.
If I run command:
netstat -nl | grep 10000
I get:
tcp 0 0 0.0.0.0:10000 0.0.0.0:* LISTEN
so the server is up and running.
My hive-site.xml settings:
<property>
<name>hive.server2.thrift.port</name>
<value>10000</value>
</property>
My code:
public class ThriftAgent {
private static final String HOST = "localhost";
private static final int PORT = 10000;
public static void main(String[] args) throws Exception {
TSocket transport = new TSocket(HOST, PORT);
transport.open();
TBinaryProtocol protocol = new TBinaryProtocol(transport);
Client client = new ThriftHive.Client(protocol);
client.execute("show tables");
final List<String> results = client.fetchAll();
for (String result : results) {
System.out.println(result);
}
transport.close();
}
}
I have tried different URL combos but it freezes at client.execute() and does not go any further than that. It does not throw any exceptions either.
I have also tried to disable authentication but that did not help either as per thread
Requests hang when using Hiveserver2 Thrift Java client
If I connect through JDBC to same host it works.
Also if I start HiveServer (not hiveserver2) it works so something is fishy with hiveserver2.
Well, with no error output to guide us, it could be several things.
It's been a while since I set up a Hive2 Server, but, you may want to define the IP address(or host) in the hive-site.xml using the hive.server2.thrift.bind.host property.
If you set the property above to 'localhost' you'll need to make certain the /etc/hosts file is set to resolve you properly, and if it's on another machine and you use the name, same thing. I would recommend testing with an IP address, and then move to name.
The comment requesting more information is a good one though, there is not much to go on here. What version of Hive2 are you using? What Hadoop distro? There will be differences affecting your solution depending on the answers.
Check if you have IPv6 disabled or in your environment settings make sure you add this to your java options:
-Djava.net.preferIPv4Stack=true
For the first one you should set this parameters on your /etc/sysctl.conf file:
#disable ipv6
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
After a reboot check if it's disabled with:
cat /proc/sys/net/ipv6/conf/all/disable_ipv6
For the second one you can add this in you hadoop-env.sh
export HADOOP_OPTS="$HADOOP_OPTS -Djava.net.preferIPv4Stack=true
or in your .bashrc file:
alias java="java -Djava.net.preferIPv4Stack=true"

Getting [SQLITE_BUSY] database file is locked with select statements

If I run multiple threads against my web app I get:
java.sql.SQLException: [SQLITE_BUSY] The database file is locked (database is locked)
at org.sqlite.DB.newSQLException(DB.java:383)
at org.sqlite.DB.newSQLException(DB.java:387)
at org.sqlite.DB.execute(DB.java:339)
at org.sqlite.PrepStmt.executeQuery(PrepStmt.java:75)
at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:96)
I do know that only one thread can write to a sqlite database but I'm only reading from the database. So why do I get this error message ?
BTW: My connection pool looks like this:
<bean class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.username}" />
<property name="password" value="${database.password}" />
<property name="initialSize" value="1" />
<property name="maxActive" value="2" />
<property name="maxIdle" value="1" />
<property name="poolPreparedStatements" value="true" />
</bean>
The setup is: Java 1.6, Tomcat 7.0.34, Spring 3.2, Hibernate 3.6.9 and sqlite3 3.7.2
Regards
Roger
After some googling I found that it is a bad practice to use multiple connections when connecting to SQLite. See
http://touchlabblog.tumblr.com/post/24474398246/android-sqlite-locking
Set your poolsize maxactive to 1 and try out.
For anyone who's having issues with it in WSL2:
Happened to me when I was using WSL2 & Datagrip, even tho the database wasn't busy.
It turns out that Datagrip has tried to connect to the database file that existed inside WSL2 via Windows' sqlite3.
Moving the file from WSL2 to a Windows file directory seems to solve this issue
There should be only ONE connection with your application.
you can use this to ensure.
public class SqliteHelper {
private static Connection c = null;
public static Connection getConn() throws Exception {
if(c == null){
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:D:/test.db");
}
return c;
}
}
Note also that this may happen if you accidentally forget to close your connection:
Connection connection;
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(QUERY);
if (resultSet.next()) { /* do something */ }
catch (SQLException e) { /* handle exception */ }
finally {
if (connection != null) {
try {
connection.close(); // <-- This is important
} catch (SQLException e) {
/* handle exception */
}
}
}
While the first database connection may work well once the server is started, subsequent queries may not, depending on how the connection pool is configured.
Everytime you establish a connection make sure to close it after the work is done, It worked for me
like if you are using
Connection con = null;
PreparedStatement pst = con.prepareStatement("...query... ");
/*
do some stuff
*/
pst.executeQuery();
pst.close();
con.close();
I experienced the same problem, even though all connections, resulsets and statements were closed, I still had the error.
The problem for me was using the DB browser plugin in Intellij to visualize and manage tables. Disconnecting the database from this tool solved the problem.
So make sure that no external tool is connecting to the database and locking tables.
In my case, there are thread using sqlite connection in the background, which caused this error.
close sqlitebrowser
close electron app ( maybe need restart)
re-run your program.
For me the problem was that I was opening too much Sessions
So I made the session field in my DAO class static
Thanks from bowman han, I added a piece of code to his solution and it worked for me.
private static Connection c = null;
public static Connection connect() throws Exception {
if (c == null) {
c = (Connection) DriverManager.getConnection(url);
} else {
c.close();
c = (Connection) DriverManager.getConnection(url);
}
return c;
}
You have opened another application containing the database,
Try to close that application and run your program again. This worked for me
Try #Transactional(readonly=true) for those methods that only do reads. Maybe that works for you.

jconsole connecting to ipv6 JMX service URL

I have trouble connecting to a JMX Service URL having an IPv6 address through jconsole. I tried
service:jmx:rmi:///jndi/rmi://[fd02:c9e3:a6c0:4306:0:0:0:27]:5500/jmx
and I get
Connection did not succeed to ..
As for some background,
I am running the jconsole from my Windows 7 box and connect to the jmx server on linux.
the jmx server is a dual stacked Redhat linux box and I am able to connect through the jconsole using the IPv4 address.
Not sure if this is relevant, the host I am trying to connect to has 2 network interfaces and one of them is used for management purposes only.
OK, I added the below condition to wrap the server host address in square brackets.
if ( aHost instanceof Inet4Address ) {
this.hostAddress = aHost.getHostAddress();
}
else if ( aHost instanceof Inet6Address ) {
this.hostAddress = "[" + aHost.getHostAddress() + "]";
}
else {
throw someException();
}
.............some other stuff.................
registry = LocateRegistry.getRegistry( this.hostAddress, ... );
In fact, the host address is specified as a name value pair in a properties file. Hence I could have done like below but it didn't work for other reasons.
.properties file
hostName = [fd02:c9e3:a6c0:4306:0:0:0:27]

Categories

Resources