jta and non jta in pe - jpa

If I mention both jta and non-jta datasource in persistence.xml, how will the provider identify what and when to use? Is there a way to enforce usage of non-jta datasource in certain scenario? I am using IBM supported OpenJPA.
Some providers allow to declare both a jta-datasource and a non-jta-datasource and use the later for optimized reading through non-JTA connections (i.e. that won't be associated to an ongoing JTA transaction). How this works and if OpenJPA supports this?
Difference between a "jta-datasource" and a " resource-local " datasource?

Probably what you want is to cofigure separate persistence units for the data sources & then injecting accordingly.
<persistence-unit name="JTA_DS" transaction-type="JTA">
<jta-data-source>java:JTA_DS</jta-data-source>
</persistence-unit>
<persistence-unit name="NON_JTA_DS" transaction-type="RESOURCE_LOCAL">
<non-jta-data-source>java:NON_JTA_DS</non-jta-data-source>
</persistence-unit>
Now you can create EnityManager for respective persistence units.
#PersistenceContext(unitName="JTA_DS")
private EntityManager _JTAManager;
#PersistenceContext(unitName="NON_JTA_DS")
private EntityManager _NonJTAManager;
Else you can build EntityManagerFactory manually as required using appropriate datasource. You can refer this link for more details.

It is difficult to understand why you mention both jta and non-jta datasource in persistence.xml. You don't need to declare both and you may need to declare one, jta or non-jta datasource.If you uses jta datasource, you will configure this in your application server and also declare in your persistence.xml.If you can't use jta datasource, you will configure JDBC connection in your persistence.xml.

Related

JPA EntityManagerFactory with AbstractRoutingDataSource containing multiple DB vendors?

So I have a perfectly good working example of using AbstractRoutingDataSource and JdbcTemplate with Oracle / Sybase & MsSql databases in the same running spring boot application. I use AOP and a custom annotation on the method so that it sets the data source name on the thread and then the AbstractDataSource hands the correct data source to JdbcTemplate when you run a query.
Now the issue I am facing, is how I go about configuring the hibernate dialects when configuring the EntityManagerFactoryBuilder, as these are obviously different and based on the underlying active data sources (can differ between environments). The code you would use to configure the EntityManagerFactory if all data sources were the same would be as follows.
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource)
.packages("<the associated entity package name>")
.build();
But when I start the spring boot application, I get the error below
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
Anyone know a workaround for this or is it not possible to have the same JPA Entities and CrudRepository instances spread across multiple datasources with different vendors?

What is a schema manager in Spring's Hibernate and how I set it?

Some tables were dropped at development environment during a spring-data-jpa project test and the developer responsible for it said it only used spring.jpa.hibernate.ddl-auto=update. Checking here, I suspected he had it set as create-drop, but since he said he didn't use, I went for this piece of information:
Spring Boot chooses a default value for you based on whether it thinks your database is embedded.
It defaults to create-drop if no schema manager has been detected
Since his application actually managed to connect to our development environment PostgreSQL database (since it dropped some tables), I start to think he maybe could have forgotten to set hbm2ddl.auto and automatically it went as create-drop.
Is it possible to connect to PostgreSQL and don't have a valid schema manager defined? Which are the most common schema managers?
PS: at this application #DataSource is set this way:
#Bean
public DataSource dataSource() {
Class.forName("org.postgresql.Driver");
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(someUrlConnectionStringFromApplicationDotPropertiesFile);
return dataSource;
}
like String someUrlConnectionStringFromApplicationDotPropertiesFile = "jdbc:postgresql://ipAddress:port/dbName?user=user&password=pass". I know spring-data-jpa sets everything with spring jpa properties automatically without this method, this is currently an unchangeable legacy code :(
Spring Boot said they are Higher-level Database Migration Tool (Flyway or Liquibase).
ref: https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-access.jpa-properties, https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-access.jpa-properties
You can also configure them through Spring Boot documentation or their own docs. ref: https://docs.spring.io/spring-boot/docs/2.7.x/reference/html/howto.html#howto.data-initialization.migration-tool
For example, configure Flyway community version through maven (https://flywaydb.org/download/community):
<build>
...
<plugin>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-maven-plugin</artifactId>
<version>9.12.0</version>
</plugin>
...
</build>

Can Jpa transaction and jdbc transaction use same datasource

I have a code which uses Hibernate Jpa transaction and an independent scheduler is written which uses jdbctransaction . My application context xml has both org.springframework.orm.jpa.JpaTransactionManager and org.springframework.jdbc.datasource.DataSourceTransactionManager beans. Can both the transaction managers use same datasource defined in xml. Or do I need to create a new datasource bean for jdbc transaction

Couchbase with Spring data using spring config example

I am a newbie to couchbase. I am using spring in my application through which I am trying to connect to couchbase in my local. I am trying to create a couchbase template(similar to what is done in mongo template) in configurations as below:
Spring configuration
Repository using couchbase template
But when I start application, I get autowiring errors and I am unable to fetch back anything. Can some please help with above issue?
Or if someone can share sample code to extract data from couchbase using sprin-data & spring configuration? Please help!
So you are using Spring Data Couchbase 1.4? The framework offers a dedicated namespace for the Spring xml configuration that you should use instead of attempting to call constructors:
xml configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:couchbase="http://www.springframework.org/schema/data/couchbase"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/data/couchbase http://www.springframework.org/schema/data/couchbase/spring-couchbase.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<couchbase:couchbase host="127.0.0.1,192.168.1.101" bucket="default" password=""/>
<couchbase:template/> <!-- will use default client above, no additional tuning-->
</beans>
First notice the xmlns:couchbase and the couchbase-specific xsi:schemaLocation in the root.
Secondly, not providing ids will wire up beans with the default IDs (and same for references, eg. the default template will reference the default client if no "client-ref" attribute is specified).
Thirdly, notice the format for the "host" parameter is just a String, hostnames or ips separated by commas (in case you want to bootstrap from a cluster).
At this point the template should be available for autowiring.
repository
For CRUD operations, Spring Data Couchbase already comes with a CRUDRepository abstraction. You only need to:
declare an interface UsersRepository extending CRUDRepository<Users, String> (string being the type of the Users field identifying it). Let's say it's in package com.test.repo.
enable building of repositories by the framework in the xml config: <repositories base-package="com.test.repo" /> (click for relevant section of the doc)
autowire your repository: #Autowired public UsersRepository repo;
The documentation has many more details about concepts like the repositories, pre-requisites for a CRUD repository to work in couchbase (short story: you need to create a view to back it up), how to model and annotate entities, etc...
Please have a look at it, at http://docs.spring.io/spring-data/couchbase/docs/1.4.0.RELEASE/reference/html/

How to use Apache-Commons DBCP with EclipseLink JPA and Tomcat 7.x

I've been working on a web application, deployed on Tomcat 7, which use EclipseLink JPA to handle the persistence layer.
Everything works fine in a test environment but we're having serious issues in the production environment due to a firewall cutting killing inactive connections. Basically if a connection is inactive for a while a firewall the sits between the Tomcat server and the DB server kill it, with the result of leaving "stale" connections in the pool.
The next time that connection is used the code never returns, until it gets a "Connection timed out" SQLException (full ex.getMessage() below).
EL Fine]: 2012-07-13
18:24:39.479--ServerSession(309463268)--Connection(69352859)--Thread(Thread[http-bio-8080-exec-5,5,main])--
MY QUERY REPLACED TO POST IT TO SO [EL Config]: 2012-07-13
18:40:10.229--ServerSession(309463268)--Connection(69352859)--Thread(Thread[http-bio-8080-exec-5,5,main])--disconnect
[EL Info]: 2012-07-13
18:40:10.23--UnitOfWork(1062365884)--Thread(Thread[http-bio-8080-exec-5,5,main])--Communication
failure detected when attempting to perform read query outside of a
transaction. Attempting to retry query. Error was: Exception
[EclipseLink-4002] (Eclipse Persistence Services -
2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException Internal
Exception: java.sql.SQLException: Eccezione IO: Connection timed out
I already tried several configuration in the persistence.xml, but since I have no access to the firewall configuration I had no luck with these methods. I also tried to use setCheckConnections()
ConnectionPool cp = ((JpaEntityManager)em).getServerSession().getDefaultConnectionPool();
cp.setCheckConnections();
cp.releaseConnection(cp.acquireConnection());
I managed to solve the issue in a test script using testOnBorrow, testWhileIdle and other features that are avalaible from DBCP Apache Commons. I'd like to know how to override the EclipseLink internal connection pool to use a custom connection pool so that I can provide an already configured pool, based on DBCP rather than just configuring the internal one using persistence.xml.
I know I should provide a SessionCustomizer, I'm uncertain which one is the correct pattern to use. Basically I would like to preserve the performance of DBCP in a JPA-like way.
I'm deploying on Tomcat 7, I know that if I switch to GF I won't have this problem, but for a matter of consistency with other webapp on the same server I'd prefere to stay on Tomcat.
What you want is definitely possible, but you might be hitting the limits of the "do it yourself" approach.
This is one of the more difficult things to explain, but there are effectively two ways to configure your EntityManagerFactory. The "do it yourself" approach and the "container" approach.
When you call Persistence.createEntityManagerFactory it eventually delegates to this method of the PersistenceProvider interface implemented by EclipseLink:
EntityManagerFactory createEntityManagerFactory(String emName, Map map)
The deal here is EclipseLink will then take it upon itself to do all the work, including its own connection creation and handling. This is the "do it yourself" approach. I don't know EclipseLink well enough to know if there is a way to feed it connections using this approach. After two days on Stackoverflow it doesn't seem like anyone else has that info either.
So here is why this "works in GF". When you let the container create the EntityManagerFactory for you by having it injected or looking it up, the container uses a different method on the PersistenceProvider interface implemented by EclipseLink:
EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map)
The long and short of it is that this PersistenceUnitInfo is an interface that the container implements and has these two very key methods on it:
public DataSource getJtaDataSource();
public DataSource getNonJtaDataSource();
With this mode EclipseLink will not try to do its own connection handling and will simply call these methods to get the DataSource from the container. This is really what you need.
There are two possible approaches you could take to solving this:
You could attempt to instantiate the EclipseLink PersistenceProvider implementation yourself and call the createContainerEntityManagerFactory method passing in your own implementation of the PersistenceUnitInfo interface and feed the DBCP configured DataSource instances into EclipseLink that way. You would need to parse the persistence.xml file yourself and feed that data in through the PersistenceUnitInfo. As well EclipseLink might also expect a TransactionManager, in which case you'll be stuck unless you hunt down a TransactionManager you can add to Tomcat.
You could use the Java EE 6 certified version of Tomcat, TomEE. DataSources are configured in the tomee.xml, created using DBCP with full support for all the options you need, and passed to the PersistenceProvider using the described createContainerEntityManagerFactory call. You then get the EntityManagerFactory injected via #PersistenceUnit or look it up.
If you do attempt to use TomEE, make sure your persistence.xml is updated to explicitly set transaction-type="RESOURCE_LOCAL" because the default is JTA. Even though it's non-compliant to use JTA with the Persistence.createEntityManagerFactory approach, there aren't any persistence providers that will complain and let you know you're doing something wrong, they treat it as RESOURCE_LOCAL ignoring the schema. So when you go to port your app to an actual certified server, it blows up.
Another note on TomEE is that in the current release, you'll have to put your EclipseLink libs in the <tomcat>/lib/ directory. This is fixed in trunk, just not released yet.
I'm not sure how useful these slides will be without the explanation that goes along with them, but the second part of this presentation is a deep dive into how container-managed EntityManager's work, specifically with regards to connection handling and transactions. You can ignore the transaction part as you aren't using them and already have an in production you're not likely to dramatically change, but it might be interesting for future development.
Best of luck!