AWS Aurora Serverless Spring Boot Communication Link Error - java

I am doing a prototype for moving our Spring Boot based application to AWS Aurora DB including Serverless mode. With Provisioned mode things work as expected. However with serverless mode the application is not able to connect to the DB from EC2 instance with exception as:
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'entityManagerFactory' defined in class path resource
[org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]:
Invocation of init method failed; nested exception is javax.persistence.PersistenceException:
[PersistenceUnit: default] Unable to build Hibernate SessionFactory;
nested exception is org.hibernate.exception.JDBCConnectionException:
Unable to open JDBC Connection for DDL execution
.....
Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException:
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago.
The driver has not received any packets from the server.
I have tried reducing the initial pool size etc but still get the same error
spring.datasource.url=jdbc:mysql://xxxxxx.cluster-xxxxxxxxxx.us-east-1.rds.amazonaws.com:3306/db_example
spring.datasource.username=xxxx
spring.datasource.password=xxxxxxx
spring.datasource.hikari.maximum-pool-size=1
spring.datasource.hikari.minimum-idle=0
spring.datasource.hikari.connection-timeout=60000
spring.jpa.database-platform=org.hibernate.dialect.MySQL5Dialect
....
When I change the Datasource to SimpleDataSource or run a simple java jdbc connection from EC2 instance it works.
#Bean("dataSource")
public DataSource dataSource() {
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
....
}
Is this normal with a Spring boot JPA/JDBC Application? Do we have to use a SimpleDriverDataSource? Perhaps are we rather supposed to use https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html? That will probably be re-writing a lot of DB related code.

In serverless mode, although highly optimized with a warn up pool of ready-to-go instances, your application requires some time until you can actually connect to Aurora.
For this reason, it is very likely that at the start of the application the connection to the database is not yet available.
It seems, for your error trace, that you are trying to do some kind of DDL operation, probably because you are using hbm2ddl to create or validate the database schema, and this operation requires a connection just while application is starting.
In order to support this kind of database architecture, you can lazily initialize your beans (which in the case of entity managers and Hibernate could be cornerstone), or look for an alternative approach for DDL generation like Liquibase (although I think the problem will remain).
You can try to tweak your Hikari connection parameters. For instance, this article propose a clever configuration and provides a great insight into AWS Aurora:
https://silexdata.com/modern-applications-and-aws-aurora-serverless/
The only thing that I do not understand is why your code works with SimpleDriverDataSource: maybe it provides some defaults that allow your app to connect to Aurora without error from the beginning.

Related

Spring MVC = The transaction is no longer active

I have a project based in Spring Web model-view-controller (MVC) framework. The version of the Spring Web model-view-controller (MVC) framework is 3.2.8 deployed on a WebLogic Server Version: 12.1.2.0.0
I have this error in 1 query
Caused By: java.lang.RuntimeException: java.sql.SQLException:
The transaction is no longer active - status: 'Marked rollback. [Reason=weblogic.transaction.internal.TimedOutException: Transaction timed out after 31 seconds
BEA1-000D9470C1367F28EDB9]'.
No further JDBC access is allowed within this transaction., criteria [ com.tdk.books.domain.ProductSearchCriteria#c5f15d5c ], sql [ select PRODUCT_ID from V_BOOKS where category_id = ? ]
even I put a timeout of 10000 in the service method
#Transactional(timeout=10000, propagation = Propagation.REQUIRES_NEW)
Root Cause from Oracle Community:
Usuallly this happens when a transaction is finished, but this fact is
ignored and an app tries to continue processing and to issue JDBC
statements that happen outside of the TX. The source of this problem
could be a Connection object that is passed around through a sequence
of methods that use the connection. One of such methods commits the TX
thus invalidating the connection.
Resource Link: https://community.oracle.com/thread/734370
Some suggestions are found to solve the issue.
First Suggestion:
Please try changing your weblogic datasource settings from Non - XA to
XA. You should get rid of this exception.
Resource Link: The transaction is no longer active - status: 'Committed'
Second Suggestion:
Uncheck the Supports Global Transactions restart the server.
Resource Link: In PRPC ERROR: The transaction is no longer active - status: 'Committed'
Third Suggestion:
The real solution of this problem is asynchronous processing. But it
might be possible that it's not suitable in your case.
First one If you are making any jdbc call to Oracle, then you can set
the query time out whn you execute the query on database. And after
query timeout, Oracle will give you an exception that you can handle
it. So basically in this case you are not cancelling your EJB request
actually. But it might solve your problem.
Resource Link: https://coderanch.com/t/68079/transaction-rollback-commit

How to start up a springboot service when DB2 connection is down

My springboot microservice depends on AS400 DB2 which may be down when the service starts up.
The service has a configuration bean which has autowired JpaRepository based repositories.
During startup, when DB2 is down I get following message:
"org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set"
So the services fails to start up and remains dead till forcefully rebooted.
If I set JVM parameter "-Dhibernate.dialect=org.hibernate.dialect.DB2400Dialect", the service starts up and I can make requests to the service when DB2 comes up. It feels like a hack, so I wonder if there is the right way to deal with this issue for springboot services?
I saw this thread, but it doesn't answer my question.
Basically what I am looking for is somehow start the microservice with those autowired repositories even if DB is down at the moment so that later, when the actual request comes, the connection to the DB could be restored and request serviced.
Have you tried to specify Hibernate dialect for your DBMS flavour in src/main/resources/application.properties like:
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.DB2400Dialect
?
Spring Boot autodetects dialect on startup if database is up but there is nothing inappropriate to specify your dialect explicitly in source code.

Java EclipseLink EntityManger: Way to Ensure Connection Can be Established?

I'm using eclipselink 2.4 in a JAX-RS (Jersey) application.
In my base controller, I connect to my database, but since the entity manager only really connects when a query is executed, an exception is thrown.
Is there a way I could determine if I can connect to a database after I get the EntityManager object so that I can handle the exception myself (and fail over manually to another database).
EDIT: assume I cannot change the underlying DBMS at all.
You could create a ServletContextListener and run a query on startup for your application. However if it fails you are out of luck for the error handling I guess.
You should really get a clustered HA database.

How can an Hibernate web application start if its database is not yet available

What would be the best way to setup/design or simply configure an Hibernate based Java web application to support being started (i.e. sessionfactory initialization) up if the database connectivity is not yet available, but will be, albeit at a much later time.
In other words, is there an easy way to handle out of order initialization between an Hibernate server application and its database?
As far as i know . If you use external connection pool and hibernate is no responsible to making the connections and in additional hbm2ddl is set to none than hibernate should not connect to the database untill you open a session.
Any way if it will failed to open session because there is no connection it will success to open new session as soon as there is databas connectivity.

WebLogic Pool Driver Doesn't Support XA driver

I am working in a typical Dev->QA->Production environment, and it appears that our Dev environment is configured differently than our QA environment, but I'm not sure where to look for the problem, as I'm not very familiar with WebLogic's core configuration.
I've developed a web service that uses the Spring framework's distributed transaction support, and all of our JNDI connection entries on the Weblogic server are configured to use the Oracle XA driver. While everything works just fine in our development environment, I am getting the following error on QA:
org.springframework.jdbc.CannotGetJdbcConnectionException:
Could not get JDBC Connection;
nested exception is java.sql.SQLException: Pool connect failed :
java.lang.Exception: WebLogic Pool Driver doesn't support XA driver,
Please change your config to use a Non-XA driver
From what I can gather, this is a configuration issue with Weblogic itself, not the individual JNDI data sources.
I know it's not a lot to go on, but if someone could give me some idea where to start looking, I would appreciate the help.
Turns out our WebLogic Admin had not restarted the connection pool as he said he did. Sorry for posting the question. Everything is working as expected now.

Categories

Resources