update of hibernate and spring security failed - spring

I would like to update hibernate 3 to 4 and spring 3 to 3.1 and spring security 3 to 3.1 in my application, but when I do this the users with authorities generated using previous versions within database are not usable and the exception
java.io.InvalidClassException GrantedAuthorityImpl local class incompatible
occurred when the application want to fetch users' authorities from database. This is the config for entity user:
#ElementCollection(targetClass = GrantedAuthority.class, fetch=FetchType.EAGER)
#CollectionTable(name = "user_authorities", schema = "mydb", joinColumns = #javax.persistence.JoinColumn(name = "user_id"))
private Collection<GrantedAuthority> authorities;

Just checked differences between master and 3.0.x branches. Your problem is in the serialization which is done by Hibernate. Judging on the JPA configuration you are storing serializable POJOs (GrantedAuthorityImpl) objects directly in to the database. That is not optimal approach. Better would be to change this to store just collection of strings.
Workaround: You can put the old GrantedAuthorityImpl source in you sources so that the classloader will prefer your version. Then you should be OK with Spring Security 3.1 and still use your approach. However that is from the hack solutions category.

Related

Spring boot with multiple database connections

I made a simple SpringBoot REST application for testing purposes where the tables are in 2 databases, one is Mysql and one is Postgresql. To configure the 2 connections I used the instructions from here, at point 6 - "Multiple Databases in Spring Boot" and all seemed to be fine, the 2 connections were initiated but only the primary connection works.
So if the Mysql connection is annotated as #Primay only Mysql REST services work, on Postgresql the error for all tables is "org.hibernate.hql.internal.ast.QuerySyntaxException: <Entity_Name> is not mapped". But if I make a single change and set #Primary on the Postgresql connection then all Postgres tables are working and all Mysql tables give the same error(table not mapped).
So somehow I think the right connection is not autoselected based on the package.
UPDATE: I found another tutorial here using different database types, I followed the instructions but the result is the same, all tables in the secondary database give the error "org.hibernate.hql.internal.ast.QuerySyntaxException: <Entity_Name> is not mapped". I think the secondary connection is not used, somehow the primary one defaults on the wrong tables but I don't know why.
I uploaded this small Github project with my work.
https://github.com/victorqedu/MultipleSpringBootDS
UPDATE: In the DAO class a have autowired the constructor and #Autowire is setting the wrong EntityManager(I think this is the source of the problem), could I manually specify the right EntityManager?
#Autowired
public AntibiogramaAntibioticeDAOHibernateImpl(EntityManager theEntityManager) {
entityManager = theEntityManager;
}
I also tried the annotation #PersistenceContext on the EntityManager but the result is the same.
#PersistenceContext
private EntityManager entityManager;
I'm not sure the problem is EntityManagaer or the Session that I obtain from EntityManager.unwrap, seems to be little documentation about this...
This can be solved with Qualifier in a short description if you have multiple same type of beans(like EntityManager) you should use qualifier to wire them.
Therefore in your code you should
public AntibiogramaAntibioticeDAOHibernateImpl(
#Qualifier("primaryEntityManagerFactory") EntityManager theEntityManager)

Spring boot native query and JPA Repository

I would like to share all my project Repository interfaces with different database implementation (PostgreSQL, MySQL, ...), but having also some specific Repository with native query, for every db platform.
How can I achieve it? Is it possible to annotate a Repository to be used only with a specific database?
if you can not do it with annotations you could find out the dialect of the database and act accordingly.
an example
private boolean isOracle() {
Session session = (Session) entityManager.getDelegate();
Dialect dialect = ((SessionFactoryImpl) session.getSessionFactory()).getJdbcServices().getDialect();
return dialect.getClass().getName().contains("Oracle");
}
so if (isOracle()) you would use your oracleJpaNativeRepository

How to obtain getUserPrincipal().getUserName() while implementing Spring Data JPA AuditorAware interface

I'm trying to use Spring Data JPA (1.6.2) in my current project. All seems to work well, but I got stuck while implementing the AuditorAware interface.
My application will be deployed to an old Apache Jetspeed JSR168 compliant portal. This portal takes care of user authentication/authorisation. As such, I don't have to use a security framework like Spring Security or Shiro. The other frameworks in my application are:
Struts 1.2.4 (with a Struts-Portal-Bridge)
Spring 3.2.10
JPA (Hibernate 3.6.10 as ORM provider)
I'd like to use #CreatedBy and #LastModifiedBy annotated fields in my entities (I got #CreatedDate and #LastModifiedDate working). In my application I usually obtain the username using request.getUserPrincipal().getUserName().
But how can I get hold of the username while implementing the AuditorAware interface?
The example implementation from the Spring Data JPA docs:
class SpringSecurityAuditorAware implements AuditorAware<User> {
public User getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return null;
}
return ((MyUserDetails) authentication.getPrincipal()).getUser();
}
}
Somehow I want to implement AuditorAware like this:
class MyAuditorAware implements AuditorAware<String> {
public String getCurrentAuditor() {
return <<principal from servlet- or portletcontext>>.getUserName();
}
}
How can I accomplish this without adding an additional framework?
As Konstantin already mentioned in his comment, you probably want to save the principal name in a scope suitable for a request. This may very well be a ThreadLocal. This allows you to get it easily later on in your AuditorAware implementation.
To stay with Spring's naming call it PrincipalContextHolder. As a starting point you may look at the source of JodaTimeContextHolder for a simple implementation of a ContextHolder.

Enabling Mandatory Validation while fetching Data from database using Spring JPA with Hibernate

I am developing an application using Spring JPA 2.0 with Hibernate as a ORM provider. We have only read only access to database and will generate report. I would like do some validation while fetching data.
#Column(name = "LOGICAL_ID", nullable = false)
#NotNull
private Long logicalId;
I added Hibernate validator which implements JSR 303 specs. But while fetching it doesn't throw any runtime exception or ConstraintViolationException? Do i add something in the configuration or am i missing something? Please advice me.
Like i've posted in Implementing cross-validation in java
You can use the following piece of code to validate an entity manually;
ValidatorFactory factory = Validation.byDefaultProvider().configure().traversableResolver(new CustomTraversableResolver() ).buildValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<YourBaseClass>> constraintViolations = Validator.validate(myEntityToValidate);
If you would like this to be done for you automatically, it might be that the 'javax.persistence.validation.mode' property is set to none (http://docs.jboss.org/hibernate/entitymanager/3.6/reference/en/html/configuration.html).
I prefer the manual validation though, since then you have control and details, of which constraints are not passing.

Spring Security user account registration, creation and management

I've been looking into using Spring Security for the authentication/authorization of my web application (this will be JDBC based).
However, a core component seems to be left out from my perspective. How do I register/create new users? Is there an out of the box API for that?
Do i need to write user registration and management from scratch?
Things i need to do include:
- Registering a new user
- Resetting passwords
- Emailing a user to activate their account
- Emailing a user to reset their account.
Thank you in advance.
I use Spring Security on my project. The framework does not have an API for user creation or registration as you asked. For Spring Security to be generic and usable across multiple frameworks, it can only take you so far before you have to write custom code. You can't really get a more specific answer about a framework or tool to use because at this point you will just use the frameworks you are already using anyway.
If you've set it up to use users and roles in your database, from your data access layer you would create a record in the user table or update a password (preferably stored as a hash) in that record. And as Aravind said, Spring does provide email support.
If you really want to see one way to do it: I'm using Spring MVC, JSP, and Hibernate. I use Spring's form tags in a JSP to bind a new user form to a Person object, and my controller method passes that Person object to my Dao to persist it.
The controller method signature looks like this...
#RequestMapping(value = "/newUser", method = RequestMethod.POST)
public ModelAndView createNewUser(final #Valid #ModelAttribute Person user,
final BindingResult result,
final SessionStatus status,
final #RequestParam(value = "unencodedPassword", required = true) String password) {
...
user.getRoles().add(new Role(user, Role.APPLICATION_ROLE.ROLE_USER));
userDao.createNewUser(user);
...
}
and my PersonDao would use Hibernate to persist the user like so
#Transactional
public void createNewUser(Person user)
{
Session session = sessionFactory.getCurrentSession();
session.save(user);
session.flush();
}
Have a look at my answer here.
"I have implemented a JAVA project for this use case. It is open
source, based on Spring-Security. A release version is on
Maven-Central, so you do not need to compile it, but instead you can
fetch it as maven-dependency to your project!"
<dependency>
<groupId>com.ohadr</groupId>
<artifactId>authentication-flows</artifactId>
<version>1.5.0-RELEASE</version>
</dependency>
As far as I know, Spring Security does not have built in support for new user creation and registration. You will have to manage this yourself. However it does have emailing support. Check here for more on this.

Resources