Cannot connect to Postgres database , there is authentication issue [duplicate] - spring

I have recently tried my hands on Postgres. Installed it on local (PostgreSQL 13.0).
Created a maven project and used Spring Data JPA, works just fine. Whereas when I tried using Gradle project, I am not able to connect to the DB and keep getting the following error.
org.postgresql.util.PSQLException: The authentication type 10 is not
supported. Check that you have configured the pg_hba.conf file to
include the client's IP address or subnet, and that it is using an
authentication scheme supported by the driver. at
org.postgresql.core.v3.ConnectionFactoryImpl.doAuthentication(ConnectionFactoryImpl.java:614)
~[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:222)
~[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:49)
~[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.jdbc.PgConnection.(PgConnection.java:194)
~[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.Driver.makeConnection(Driver.java:450)
~[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.Driver.connect(Driver.java:252)
~[postgresql-42.1.4.jar:42.1.4] at
java.sql.DriverManager.getConnection(Unknown Source) [na:1.8.0_261]
at java.sql.DriverManager.getConnection(Unknown Source)
[na:1.8.0_261] at
org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:94)
[postgresql-42.1.4.jar:42.1.4] at
org.postgresql.ds.common.BaseDataSource.getConnection(BaseDataSource.java:79)
[postgresql-42.1.4.jar:42.1.4]
I tried using JDBCTemplate as well. Doesn't work
Modified the pg_hba.cfg file referring to this post - Doesn't work
Used the deprecated Lib of - Doesn't Work either.
Please Suggest me a solution for this problem.
My code and Config:
#Configuration
public class DataSourceConfig {
#Bean
public DriverManagerDataSource getDataSource() {
DriverManagerDataSource dataSourceBuilder = new DriverManagerDataSource();
dataSourceBuilder.setDriverClassName("org.postgresql.Driver");
dataSourceBuilder.setUrl("jdbc:postgresql://localhost:5432/postgres");
dataSourceBuilder.setUsername("postgres");
dataSourceBuilder.setPassword("root");
return dataSourceBuilder;
}
}
#Component
public class CustomerOrderJDBCTemplate implements CustomerOrderDao{
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
#Autowired
ApplicationContext context;
public void setDataSource() {
//Getting Bean by Class
DriverManagerDataSource dataSource = context.getBean(DriverManagerDataSource.class);
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(this.dataSource);
}
#Override
public Customer create(Customer customer) {
setDataSource();
String sql = "insert into CustomerOrder (customerType, customerPayment) values (?, ?)";
//jdbcTemplateObject.update(sql, customerOrder.getCustomerOrderType(), customerOrder.getCustomerOrderPayment());
KeyHolder holder = new GeneratedKeyHolder();
jdbcTemplateObject.update(new PreparedStatementCreator() {
#Override
public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
PreparedStatement ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
ps.setString(1, customer.getType());
ps.setString(2, customer.getPayment());
return ps;
}
}, holder);
long customerId = holder.getKey().longValue();
customer.setCustomerID(customerOrderId);
return customer;
}
}
dependencies
implementation('org.springframework.boot:spring-boot-starter-web')
compile("org.springframework.boot:spring-boot-devtools")
compile(group: 'org.postgresql', name: 'postgresql', version: '42.1.4')
compile("org.springdoc:springdoc-openapi-ui:1.4.1")
compile("org.springframework:spring-jdbc:5.2.5.RELEASE")
password_encryption is set like this:
postgres=# show password_encryption;
password_encryption
---------------------
scram-sha-256
(1 row)

I solved similar issue by applying below steps in PostgreSQL Version 13:
Change password_encryption to md5 in postgresql.conf
Windows: C:\Program Files\PostgreSQL\13\data\postgresql.conf
GNU/Linux: /etc/postgresql/13/main/postgresql.conf
Change scram-sha-256 to md5 in pg_hba.conf
Windows: C:\Program Files\PostgreSQL\13\data\pg_hba.conf
GNU/Linux: /etc/postgresql/13/main/pg_hba.conf
host all all 0.0.0.0/0 md5
Change Password ( this restore password in md5 format).
Example: ALTER ROLE postgres WITH PASSWORD 'root';
Make sure you set listen_addresses = '*' in postgresql.conf if you are working non production environment.

According to the wiki, the supported JDBC driver for SCRAM-SHA-256 encryption is 42.2.0 or above.
In my case, the driver was 41.1.1. Change it to 42.2.0 or above. That fixed it for me.
(Maven, pom.xml):
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.0</version>
</dependency>

Get your pg_hba.conf File in the Directory
C:\Program Files\PostgreSQL\13\data\pg_hba.conf
And Simply Change scram-sha-256 under Column Method to trust.
It worked For me!

By setting password_encryption to scram-sha-256 (which is the default value in v13) you also get scram-sha-256 authentication, even if you have md5 in pg_hba.conf.
Now you are using an old JDBC driver version on the client side that does not support that authentication method, even though PostgreSQL introduced it in v10, three years ago.
You should upgrade your JDBC driver. An alternative would be to set password_encryption back to md5, but then you'll have to reset all passwords and live with lower security.

<?xml version="1.0" encoding="UTF-8"?>
4.0.0
<groupId>org.example</groupId>
<artifactId>postgresJDBC</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<java.version>11</java.version>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.source>${java.version}</maven.compiler.source>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.18</version>
</dependency>
</dependencies>
you have to check your maven dependency if you are using postgresql 9.1+ then your dependency should be like above
to know about maven dependency refer this link How do you add PostgreSQL Driver as a dependency in Maven?

Change METHOD to "trust" in pg_hba.conf

In case you are struggling to get this working in Docker:
Firstly: run the container with -e POSTGRES_HOST_AUTH_METHOD=md5 (doc)
docker run -e POSTGRES_HOST_AUTH_METHOD=md5 -e POSTGRES_PASSWORD=doesntmatter -p 5432:5432 --name CONTAINERNAME -d postgres
Secondly: allow md5 encryption as discussed in other answers:
docker exec -ti -u postgres CONTAINERNAME bash -c "echo 'password_encryption=md5' >> /var/lib/postgresql/data/postgresql.conf"
Thirdly: restart the container
docker restart CONTAINER NAME
Fourthly: you need to recreate the postgres password in md5 format
docker exec -ti -u postgres CONTAINERNAME psql
alter role postgres with password 'THE-NEW-PASSWORD';
* please be aware scram-sha-256 is much better than md5 (doc)

use these :
wget https://jdbc.postgresql.org/download/postgresql-42.2.24.jar
Copy it to your hive library
sudo mv postgresql-42.2.24.jar /opt/hive/lib/postgresql-42.2.24.jar

For me, updating the postgres library helped fixing this.

working fine with version 12.6 ... just downgrade the PostgreSQL

You might need to check the version of Postgres you are running. Migh need to update spring version if the version is being pointed through spring parent.
In my case: since current postgres is at v13. Modified spring parent version: it was on 1.4; made it to match to 2.14. Finally update maven dependency and re-run the application.This fixed the issue.

Suggestions:
Current JDBC driver will help (e.g. postgresql-42.3.6.jar)
Copy it to the /jars folder under your spark install directory (I'm assuming a single machine here in this example)
Python - install "findspark" to make pyspark importable as a regular library
Here is an example I hope will help someone:
import findspark
findspark.init()
from pyspark.sql import SparkSession
sparkClassPath = "C:/spark/spark-3.0.3-bin-hadoop2.7/jars"
spark = SparkSession \
.builder \
.config("spark.driver.extraClassPath", sparkClassPath) \
.getOrCreate()
df = spark.read \
.format("jdbc") \
.option("url", "jdbc:postgresql://{YourHostName}:5432/{YourDBName}") \
.option("driver", "org.postgresql.Driver") \
.option("dbtable", "{YourTableName}") \
.option("user", "{YourUserName") \
.option("password", "{YourSketchyPassword") \
.load()
Install pgadmin if you have not already done so.
Try it via Docker

You need to download postgresql..jar and then move it into .../jre/lib/ext/ folder. It worked for me

Even after changing pg_hba.conf to MD5 on everything it didn't work.
What worked was doing this:
show password_encryption;
If it shows up as being scram-sha-256 do this:
set password_encryption = 'md5';
Restart server, this solved my issue

Use latest maven dependency for Postgres in pom.xml

Changing trust for ipv4 local connect worked for me.
Solution:
Get your pg_hba.conf File in the Directory C:\Program Files\PostgreSQL\13\data\pg_hba.conf
And Simply Change scram-sha-256 under Column Method to trust.

I guess the solution to this problem is using version 9.6.
It works just fine after changing the version.

Open pg_hba.conf
Set IPv4 local connections to trust

Related

How to install JDBC driver on Databricks Cluster?

I'm trying to get the data from my Oracle Database to a Databricks Cluster. But I think I'm doing it wrong:
On the cluster library I just installed the ojdbc8.jar and then after that I opened a notebook and did this to connect:
CREATE TABLE oracle_table
USING org.apache.spark.sql.jdbc
OPTIONS (
dbtable 'table_name',
driver 'oracle.jdbc.driver.OracleDriver',
user 'username',
password 'pasword',
url 'jdbc:oracle:thin://#<hostname>:1521/<db>')
And it says:
java.sql.SQLException: Invalid Oracle URL specified
Can someone help? I've been reading documentations but there's no clear instruction on how I should actually install this jar step by step. I might be using the wrong jar? Thanks!
I have managed to set this up in Python/PySpark as follows:
jdbcUrl = "jdbc:oracle:thin:#//hostName:port/databaseName"
connectionProperties = {
"user" : username,
"password" : password,
"driver" : "oracle.jdbc.driver.OracleDriver"
}
query = "(select * from mySchema.myTable )"
df = spark.read.jdbc(url=jdbcUrl, table=query1, properties=connectionProperties)
I am using the Oracle JDBC Thin Driver instantclient-basic-linux.x64-21.5.0.0.0, as available on the Oracle webpages. The current version is 21.7 I think, but it should work the same way.
Check this link to understand the two different notations for jdbc URLs

Getting exception "Not using JDBC" while using quarkus-hibernate-reactive-panache with quarkus-reactive-mysql-client - (Quarkus 1.12.2.Final)

Quarkus 1.12.2.Final
Getting the following exception while using reactive hibernate (quarkus-hibernate-reactive-panache) with reactive MySQL client (quarkus-reactive-mysql-client), kindly suggests what could be the issue.
2021-04-01 11:35:28,694 ERROR [org.hib.eng.jdb.spi.SqlExceptionHelper] (Quarkus Main Thread) Not using JDBC
2021-04-01 11:35:28,727 ERROR [io.qua.run.Application] (Quarkus Main Thread) Failed to start application (with profile dev): java.sql.SQLException: Not using JDBC
at org.hibernate.reactive.provider.service.NoJdbcConnectionProvider.getConnection(NoJdbcConnectionProvider.java:25)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180)
Some details
My application.properties
quarkus.datasource.jdbc=false
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=root
quarkus.datasource.password=root
quarkus.datasource.reactive.url=mysql://localhost:3306/mydb
quarkus.datasource.reactive.max-size=20
My Repository Implementation
#ApplicationScoped public class EventRepository implements PanacheRepository<Event> {
}
Change your application.properties to
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=root
quarkus.datasource.password=root
quarkus.datasource.reactive.url=vertx-reactive:mysql://localhost:3306/mydb
quarkus.datasource.reactive.max-size=20
Here is the cause of the problem -> I used property "quarkus.hibernate-orm.database.generation=update". It seems like the use of this property requires JDBC connection, removed it, and it's working fine.
Any of the below config sets can work.
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=****
quarkus.datasource.password=****
quarkus.datasource.reactive.url=mysql://localhost:3306/db
or
quarkus.datasource.reactive.url=vertx-reactive:mysql://localhost:3306/db
"The latest version available of Hibernate Reactive doesn't support schema update and validation yet."
Relative issue here:
Not using JDBC problem met in native build · Issue #19918 · quarkusio/quarkus · GitHub
Can you try to add the following property to your settings?
quarkus.hibernate-orm.database.generation=update
You can write drop-and-create to re-create your db when you run your server as well. See details here.
Hmm. JDBC and Hibernate update should work in your case. Do you have a JDBC extension (dependency) in your project? If not, try to ad one.
In case of a postgres you can add extension this way:
./mvnw quarkus:add-extension -Dextensions="jdbc-postgresql
More info here
Add the agroal extension plus one of jdbc-db2, jdbc-derby, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle or jdbc-postgresql.
https://quarkus.io/guides/datasource
Add this dependency to your pom.xml file.
<!-- https://mvnrepository.com/artifact/io.quarkus/quarkus-jdbc-postgresql -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
<version>2.9.2.Final</version>
</dependency>

DriverManager tries to use mariadb driver when connecting to h2 database

I'm doing some testing and got the following exception:
java.lang.IllegalArgumentException: Invalid connection URL url dbc:h2:db/test
at org.mariadb.jdbc.JDBCUrl.parse(JDBCUrl.java:144)
at org.mariadb.jdbc.Driver.connect(Driver.java:95)
at java.sql.DriverManager.getConnection(DriverManager.java:664)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
The code I'm using:
Class.forName("org.h2.Driver"); //load h2 driver
String connectionUrl = "jdbc:h2:db/test";
Connection conn = DriverManager.getConnection(connectionUrl, "sa", "");
I also test something related to mariadb/mysql, so the mariadb driver is also on classpath in addition to the h2 driver (eclipse project). If I remove the mariadb driver from classpath the connection works.
To my knowledge it should be possible to have multiple jdbc drivers on classpath or have I understood something wrong?
(h2 is version 1.3.176 and mariadb-java-client is 1.2.0)
EDIT: Using mariadb-java-client 1.2.2 removes the problem
I can confirm that this was a bug in the mariadb-jdbc-driver
https://mariadb.atlassian.net/plugins/servlet/mobile#issue/CONJ-167
I would assume this was some kind of bug, since I have not seen the problem after updating to mariadb-java-client 1.2.2 .

Not able to connect to hive on AWS EMR using java

I have setup AWS EMR cluster with hive. I want to connect to hive thrift server from my local machine using java. I tried following code-
Class.forName("com.amazon.hive.jdbc3.HS2Driver");
con = DriverManager.getConnection("jdbc:hive2://ec2XXXX.compute-1.amazonaws.com:10000/default","hadoop", "");
http://docs.aws.amazon.com/ElasticMapReduce/latest/DeveloperGuide/HiveJDBCDriver.html.As mentioned in the developer guide, added jars related with hive jdbc driver to class path.
But I am getting exception when trying to get connection.
I was able to connect to hive server on simple hadoop cluster using above code (with different jdbc driver).
Can someone please suggest if I am missing something?
Is it possible to connect to hive server on AWS EMR from local machine using hive jdbc?
(Merged Answer from the comments)
Hive is running on port 10000 but only locally, you have to create a ssh tunnel to the emr.
The following is from the documentation for hive 0.13.1
Create Tunnel
ssh -o ServerAliveInterval=10 -i path-to-key-file -N -L 10000:localhost:10000 hadoop#master-public-dns-name
Connect to JDBC
jdbc:hive2://localhost:10000/default
You can use the code using the library JSch
public static void portForwardForHive() {
try {
if(session != null && session.isConnected()) {
return;
}
JSch jsch = new JSch();
jsch.addIdentity(PATH_TO_SSH_KEY_PEM);
String host = REMOTE_HOST;
session = jsch.getSession(USER, host, 22);
// username and password will be given via UserInfo interface.
UserInfo ui = new MyUserInfo();
session.setUserInfo(ui);
session.connect();
int assingedPort = session.setPortForwardingL(LPORT, RHOST, RPORT);
System.out.println("Port forwarding done for the post : " + assingedPort);
} catch (Exception e) {
System.out.println(e);
}
}
Not sure if you've resolved this yet, but its a bug in EMR that's just bitten me.
For direct jdbc connectivity like you are doing, you must include the jdbc drivers in your shaded uber-jar. For jdbc access from within dataframes, you cannot access the jar in your uber-jar (another unrelated bug), but you must specify it on the command line (S3 is a convenient place to keep them):
--files s3://mybucketJAR/postgresql-9.4-1201.jdbc4.jar
However, even after this you will run into another problem if you are specifically trying to access hive. Amazon has built their own jdbc drivers with a different class hierarchy to the normal hive driver (com.amazon.hive.jdbc41.HS2Driver), however the EMR cluster includes the standard Hive jdbc driver in its standard path (org.apache.hive.jdbc.HiveDriver).
This is automatically registered as being capable of handling the jdbc:hive and jdbc:hive2 urls, so when you try to connect to a hive URL it finds this one first and uses it - even if you specifically register the amazon one. Unfortunately, this one is not compatible with amazon's EMR build of Hive.
There are two possible solutions:
1: Find the offending driver and unregister it:
Scala example:
val jdbcDrv = Collections.list(DriverManager.getDrivers)
for(i <- 0 until jdbcDrv.size) {
val drv = jdbcDrv.get(i)
val drvName = drv.getClass.getName
if(drvName == "org.apache.hive.jdbc.HiveDriver") {
log.info(s"Deregistering JDBC Driver: ${drvName}")
DriverManager.deregisterDriver(drv)
}
}
Or
2: As I found out later, you can specify the driver as part of the connect properties when you attempt to connect:
Scala example:
val hiveCredentials = new java.util.Properties
hiveCredentials.setProperty("user", hiveDBUser)
hiveCredentials.setProperty("password", hiveDBPassword)
hiveCredentials.setProperty("driver", "com.amazon.hive.jdbc41.HS2Driver")
val conn = DriverManager.getConnection(hiveDBURL, hiveCredentials)
This is a more "correct" version as it should override any preregistered handlers even if they have completely different class hierarchies.

How to access Spring-boot JMX remotely

I know that spring automatically expose JMX beans. I was able to access it locally using VisualVM.
However on prod how I can connect to remotely to the app using it's JMX beans? Is there a default port or should I define anything in addition?
Thanks,
ray.
By default JMX is automatically accessible locally, so running jconsole locally would detect all your local java apps without port exposure.
To access an app via JMX remotely you have to specify an RMI Registry port. The thing to know is that when connecting, JMX initializes on that port and then establishes a data connection back on a random high port, which is a huge problem if you have a firewall in the middle. ("Hey sysadmins, just open up everything, mkay?").
To force JMX to connect back on the same port as you've established, you have a couple of the following options. Note: you can use different ports for JMX and RMI or you can use the same port.
Option 1: Command line
-Dcom.sun.management.jmxremote.port=$JMX_REGISTRY_PORT
-Dcom.sun.management.jmxremote.rmi.port=$RMI_SERVER_PORT
If you're using Spring Boot you can put this in your (appname).conf file that lives alongside your (appname).jar deployment.
Option 2: Tomcat/Tomee configuration
Configure a JmxRemoteLifecycleListener:
Maven Jar:
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-catalina-jmx-remote</artifactId>
<version>8.5.9</version>
<type>jar</type>
</dependency>
Configure your server.xml:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener"
rmiRegistryPortPlatform="10001" rmiServerPortPlatform="10002" />
Option 3: configure programmatically
#Configuration
public class ConfigureRMI {
#Value("${jmx.rmi.host:localhost}")
private String rmiHost;
#Value("${jmx.rmi.port:1099}")
private Integer rmiPort;
#Bean
public RmiRegistryFactoryBean rmiRegistry() {
final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
rmiRegistryFactoryBean.setPort(rmiPort);
rmiRegistryFactoryBean.setAlwaysCreate(true);
return rmiRegistryFactoryBean;
}
#Bean
#DependsOn("rmiRegistry")
public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi://%s:%s/jndi/rmi://%s:%s/jmxrmi", rmiHost, rmiPort, rmiHost, rmiPort));
return connectorServerFactoryBean;
}
}
The trick, you'll see, is the serviceUrl in which you specify both the jmx:rmi host/port and the jndi:rmi host/port. If you specify both, you won't get the random high "problem".
Edit: For JMX remoting to work, you'll need to make a decision about authenticating. It's better to do it in 3 distinct steps: 1) basic setup with -Dcom.sun.management.jmxremote.authenticate=false then 2) add a password file (-Dcom.sun.management.jmxremote.password.file). See here for instructions. + -Dcom.sun.management.jmxremote.ssl=false and then 3) set up SSL.
Add the following JVM Properties in "$JAVA_OPTS" (in your application):
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=<PORT_NUMBER> -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=<HOST'S_IP>
In the Jconsole/Visual VM use the following to connect:
service:jmx:rmi:///jndi/rmi://<HOST'S_IP>:<PORT_NUMBER>/jmxrmi
It doesn't enable security, but will help you to connect to the remote server.
A tested approach on Java 1.8.0_71 and Spring Boot(1.3.3.RELEASE).
Append below parameters to JVM arguments for monitored JVM.
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=12348 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.rmi.port=12349 -Dcom.sun.management.jmxremote.password.file=/somewhere/jmxremote.password -Dcom.sun.management.jmxremote.access.file=/somewhere/jmx/jmxremote.access
The com.sun.management.jmxremote.port is used to define the fixed RMI registry port, and the com.sun.management.jmxremote.rmi.port is used to instruct JVM to use fixed RMI port, but NOT use random one.
By setting this, I am able to connect JVM client from remote host to the monitored JVM via a firewall just opening 12348 and 12349 port.
I tested using java -jar cmdline-jmxclient-0.10.3.jar user:pwd hostip:12348 on a remote machine, which generates below output(shortened just for demonstration).
java.lang:type=Runtime
java.lang:name=PS Scavenge,type=GarbageCollector
Tomcat:J2EEApplication=none,J2EEServer=none,WebModule=//localhost/,j2eeType=Filter,name=requestContextFilter
java.nio:name=mapped,type=BufferPool
Tomcat:host=localhost,type=Host
java.lang:name=Compressed Class Space,type=MemoryPool
.......
The jar is downloaded from Here.
Another alternative
Reference for jmxremote.password and jmxremote.access files
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.jmx.support.ConnectorServerFactoryBean;
import org.springframework.remoting.rmi.RmiRegistryFactoryBean;
#Configuration
public class ConfigureRMI {
#Value("${jmx.rmi.password.file:/tmp/jmxremote.password}")
private String passwordFile;
#Value("${jmx.rmi.access.file:/tmp/jmxremote.access}")
private String accessFile;
#Value("${jmx.rmi.port:19999}")
private Integer rmiPort;
#Bean
public RmiRegistryFactoryBean rmiRegistry() {
final RmiRegistryFactoryBean rmiRegistryFactoryBean = new RmiRegistryFactoryBean();
rmiRegistryFactoryBean.setPort(rmiPort);
rmiRegistryFactoryBean.setAlwaysCreate(true);
return rmiRegistryFactoryBean;
}
#Bean
#DependsOn("rmiRegistry")
public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
connectorServerFactoryBean.setObjectName("connector:name=rmi");
Map<String, Object> properties = new HashMap<>();
properties.put("jmx.remote.x.password.file", passwordFile);
properties.put("jmx.remote.x.access.file", accessFile);
connectorServerFactoryBean.setEnvironmentMap(properties);
connectorServerFactoryBean.setServiceUrl(String.format("service:jmx:rmi:///jndi/rmi://:%s/jmxrmi", rmiPort));
return connectorServerFactoryBean;
}
}

Resources