inserting records in two databases using jpa + hibernate + spring - spring

We have the requirement to insert records into two data sources using JPA.
What is the correct approach to this problem?
How can we declare different persistence units with different data sources and manage two entity managers and inject with default persistence context for default unit name without mentioning the unit name in the generic dao for first datasource and overriding the context with the unit name in a separate dao for other tables in second datasource.
The spring documentation is very limited and has no example.
Examples would be of great help.

Use
<bean class="..." primary="true" />
or #Primary if you are using annotations.
This will indicated that one instance is the "default" instance of a type that you define multiple different instances of (like your EntityManagerFactory).

If you follow this tutorial, http://javacodegeeks.blogspot.com/2010/05/jboss-42x-spring-3-jpa-hibernate.html you can make the following changes to access two different databases:
persistence.xml, define a second pesristence-unit for your second database.
spring.xml, define a second entityManagerFactory bean under a different name, lets say "entityManagerFactoryDB2" and configure it to use the persistent unit for the second database.
for every DAO you want to access the second database include the following :
#Autowired
private EntityManagerFactory entityManagerFactoryDB2;
#PostConstruct
public void init() {
super.setEntityManagerFactory(entityManagerFactoryDB2);
}
Thats all!
On spring service classes, use the DAOs as usual!

Related

How to avoid the vulnerability created by using entities at a requestMapping method?

I have a controller with a method like
#PostMapping(value="/{reader}")
public String addToReadingList(#PathVariable("reader") String reader, Book book) {
book.setReader(reader);
readingListRepository.save(book);
return "redirect:/readingList/{reader}";
}
When I run a static code analysis with Sonarqube I get a vulnerability report stating that
Replace this persistent entity with a simple POJO or DTO object
But if I use a DTO (which has exactly the same fields as the entity class, then I get another error:
1 duplicated blocks of code must be removed
What should be the right solution?
Thanks in advance.
Enric
You should build a new separate class which represents your Entity ("Book" ) as Plain Old Java Object (POJO) or Data Transfer Object (DTO). If you use JSF or other stateful technology this rule is important. If your entity is stateful there might be open JPA sessions etc. which may modify your database (e.g. if you call a setter in JSF on a stateful bean).
For my projects I ignore this Sonar rule because of two reasons:
I alway you REST and REST will map my Java Class into JSON which can be seen as a DTO.
REST is stateless (no server session) so no database transaction will be open after the transformation to JSON
Information obtained from sonarsource official documentation.
On one side, Spring MVC automatically bind request parameters to beans
declared as arguments of methods annotated with #RequestMapping.
Because of this automatic binding feature, it’s possible to feed some
unexpected fields on the arguments of the #RequestMapping annotated
methods.
On the other end, persistent objects (#Entity or #Document) are linked
to the underlying database and updated automatically by a persistence
framework, such as Hibernate, JPA or Spring Data MongoDB.
These two facts combined together can lead to malicious attack: if a
persistent object is used as an argument of a method annotated with
#RequestMapping, it’s possible from a specially crafted user input, to
change the content of unexpected fields into the database.
For this reason, using #Entity or #Document objects as arguments of
methods annotated with #RequestMapping should be avoided.
In addition to #RequestMapping, this rule also considers the
annotations introduced in Spring Framework 4.3: #GetMapping,
#PostMapping, #PutMapping, #DeleteMapping, #PatchMapping.
See More Here

how can I have a datasource object that is not a bean in spring?

This might sound weird. But I want to know how/if I can create datasource objects during runtime and not when the container start-up.
Here is the problem I am working on:
I have a MySql database which stores the URL, userName and password for other SQL Servers that I need to connect and do overnight processing. This list of SQL Servers changes everytime. so it cannot be hard-coded in properties files. Further, the no of SQL servers is about 5000 or more.
The business logic involves reading the MySQL database (which is currently a datasource bean created during container start-up) and for each entry in SQL_SERVER_MAPPING table in MySQL database, I need to connect to that database and run reports.
I was thinking of doing something along this line for each of the SQL server instances
public DataSource getdataSource(String url, String u, String p, String class) {
return DataSourceBuilder
.create()
.username(u)
.password(p)
.url(url)
.driverClassName(class)
.build();
}
public JdbcTemplate jdbcTemplate(DataSource datasource) {
return new JdbcTemplate(dataSource);
}
Here is a builder that generates datasource for a given url and create the necessary jdbcTemplate from it. so basically create one for each of SQL server configurations.
My concern is I will be creating about 5000 datasources and 5000 jdbcTemplate or perhaps even more. That doesn't sound right to me. what is the right way to get around here?
is there a way to remove datasource objects as soon I am done with it or recycle them?
should I cache these dataSource objects in my Spring application, so I dont have to create one each time and discard it. but this implies, I need to cache 5000 (or probably more in the future).
Spring docs says
The DataSource should always be configured as a bean in the Spring IoC container. In the first case the bean is given to the service directly; in the second case it is given to the prepared template.
so that makes things harder for me.
Thanks
You can define a bean myBean with scope prototype and use the getBean(String name, Object... args) method of a BeanFactory. args would be the args sent to the constructor (in your case these would be db connections). The bean would return a jdbcTemplate constructed with a datasource defined from the connection properties. This template can be further used in other classes.
Since the scope of the bean is prototype, the created instances will be garbaged collected after the current object is used. This can help if you have memory constraints, the really heavy lifting in terms of creating objects is done when getting the actual DB connections. Caching would be a good solution in case of heavy re-usage of connections.
See an example of this bean and method usage here: spring bean with dynamic constructor value

Spring+hibernate+jpa how does it work?

In the new project that I have joined, they keep using the terms Hibernate and JPA interchangeably. So, I tried to dive down into the code and try to understand how this whole thing works (I am new to Spring, JPA and Hibernate world). I'll try to put the code here for better understanding:
1) There is a #Configuration class where they have the following:
#Resource
private HibernateJpaVendorAdapter hibernateOracleJpaVendorAdapter;
LocalContainerEntityManagerFactoryBean entityManager =
new LocalContainerEntityManagerFactoryBean();
entityManager.setJpaVendorAdapter(hibernateOracleJpaVendorAdapter);
entityManager.setPersistenceUnitName("abc");
.
.
So, in this configuration class, we are returning an EntityManagerFactory.
2) Then there is a persistor class marked #Persistor, where a method of repository is invoked (for example, for a save operation):
blahblahRepository.save(blahblahEntity, abcdef);
3) Finally there is a repository class which is annotated #Repository. Then again, they have this piece of code:
#PersistenceContext(unitName = "same as the name in persistence.xml")
protected EntityManager entityManager;
The "save" method wraps around the persist method of JPA:
getEntityManager().persist(entityObject);
My questions are as follows:
1) There is no word about Hibernate other than in the hibernateJpaVendorAdapter. I searched the entire workspace and it showed just 3 occurences of the word hibernate, all in the configuration file.
2) From whatever knowledge I have, one should use either an EntityManagerFactory or an EntityManager but we are doing both?
Hibernate is one of the implementations of the JPA spec. Since your project chose Hibernate as its JPA implementation, it uses the JPA API, which delegates the Hibernate. Just like when you use the JDBC API, which delegates to a specific Oracle or PostgreSQL driver.
EntityManagerFactory, as its name indicates, is a factory for EntityManager. I don't see why you wouldn't use both. EntityManager is the main interface of the JPA API, used to execute all database operations (find, persist, merge, query, etc.). EntityManagerFactory must be configured before asking it to create an EntityManager.

How to manage transactions with JAX-RS, Spring and JPA

I'm using JAX-RS to provide an HTTP-based interface to manage a data model. The data model is stored in a database and interacted with via JPA.
This allows me to modify the interface to the data model to suit REST clients and mostly seems to work quite well. However, I'm not sure how to handle the scenario where a method provided by a JAX-RS resource requires a transaction, which affects the JPA get, update, commit-on-tx-end pattern, because there is only a transaction wrapping the get operation, so the update is never committed. I can see the same problem occurring if a single REST operation requires multiple JPA operations.
As I'm using Spring's transaction support, the obvious thing to do is to apply #Transactional to these methods in the JAX-RS resources. However, in order for this to work, Spring needs to manage the lifecycle of the JAX-RS resources, and the useage examples I'm aware of have resources being created via `new' when needed, which makes me a little nervous anyway.
I can think of the following solutions:
update my JPA methods to provide a transaction-managed version of everything I want to do from my REST interface atomically. Should work, keeps transactions out of the JAX-RS layer, but prevents the get, update, commit-on-tx-end pattern and means I need to create a very granular JPA interface.
Inject Resource objects; but they are typically stateful holding at least the ID of the object being interacted with
Ditch the hierarchy of resources and inject big, stateless super resources at the root that manage the entire hierarchy from that root; not cohesive, big services
Have a hierarchy of injected, stateless, transaction-supporting helper objects that 'shadow' the actual resources; the resources are instantiated and hold ths state but delegate method invocations to the helper objects
Anyone got any suggestions? It's quite possible I've missed some key point somewhere.
Update - to work around the lack of a transaction around the get, update, commit-on-tx-close flow, I can expose the EntityManager merge(object) method and call it manually. Not neat and doesn't solve the larger problem though.
Update 2 #skaffman
Code example:
In JPA service layer, injected, annotations work
public class MyEntityJPAService {
...
#Transactional(readOnly=true) // do in transaction
public MyEntity getMyEntity(final String id) {
return em.find(MyEntity.class, id);
}
In JAX-RS resource, created by new, no transactions
public class MyEntityResource {
...
private MyEntityJPAService jpa;
...
#Transactional // not injected so not effective
public void updateMyEntity(final String id, final MyEntityRepresentation rep) {
MyEntity entity = jpa.getMyEntity(id);
MyEntity.setSomeField(rep.getSomeField());
// no transaction commit, change not saved...
}
I have a few suggestions
Introduce a layer between your JPA and JAX-RS layers. This layer would consist of Spring-managed #Transactional beans, and would compose the various business-level operations from their component JPA calls. This is somewhat similar to your (1), but keeps the JPA layer simple.
Replace JAX-RS with Spring-MVC, which provides the same (or similar) functionality, including #PathVariable, #ResponseBody, etc.
Programmatically wrap your JAX-RS objects in transactional proxies using TransactionProxyFactorybean. This would detct your #Transactional annotations and generate a proxy that honours them.
Use #Configurable and AspectJ LTW to allow Spring to honour #Transactional even if you create the object using `new. See 8.8.1 Using AspectJ to dependency inject domain objects with Spring

object creation in spring

If I am using spring frame work in my application does creating an object like this Test test = new Test() a bad way for creating an instance? Should I always use the bean config to get the objects/bean that I need? If yes, does that means I should have all the object/bean definition in spring applicationContext xml file?
If you want your object to be managed by Spring (this means that dependencies are injected, among other things) you have to use the ApplicationContext.
Calling Test test = new Test() isn't illegal, or even bad practice. It just means that Spring will have no awareness of this object, and it won't bother autowiring it's dependencies, or doing anything else that you'd expect Spring to do.
You don't necessarily need to use the applicationContext.xml file for ALL of your bean declarations. Many people favor annotations, which allow you to declare beans outside of the applicationContext.xml file.
It's worth nothing that Spring-managed beans are by default singletons (think of Servlets). If you want stateful beans that are Spring aware, you could use an ObjectFactoryCreatingFactoryBean to do something like this:
#Autowired
private ObjectFactory myWidgetFactory;
public void doStuff() {
Widget w = myWidgetFactory.getObject();
}
You can read more about this behaviour here:
http://static.springsource.org/spring/docs/3.0.x/api/org/springframework/beans/factory/config/ObjectFactoryCreatingFactoryBean.html
For me there's a big difference between objects that represent components of my application -- services, controllers, DAOs, utilities, etc. -- and objects that represent entities within my application -- Person, Order, Invoice, Account, etc. The former type of objects should absolutely be managed by Spring and injected. The latter type are typically created on the fly by the application, and that frequently will involve calling new. This is not a problem.
Test test = new Test() a bad way for
creating an instance?
Yes it is bad practice.
Should I always use the bean config
to get the objects/bean that I need?
Yes, if you are using Spring for dependency injection.
If yes, does that means I should have
all the object/bean definition in
spring applicationContext xml file?
Always! You could use Annotations too.

Resources