0

Yes I've seen similar questions, but none of the answers actually led me to a solution. I'm not using the thread anywhere, and this same code works in another jhipster app, so I'm stumped why this lift+shift is causing Hibernate problems.

public UserDetailsContextMapper userDetailsContextMapper() {
    return new UserDetailsContextMapper() {
        @Override
        public UserDetails mapUserFromContext(
            DirContextOperations ctx, String username,
            Collection<? extends GrantedAuthority> authorities) {
            log.error("2 " + username + " -> " + ctx.toString());
            String lowercaseLogonName = username.toLowerCase();
            Optional<User> userFromDatabase = userRepository.findOneByLogin(lowercaseLogonName);
            if (!userFromDatabase.isPresent()) {
                User ldapUser = new User();
                ldapUser.setLogin(lowercaseLogonName);
                ldapUser.setPassword(RandomStringUtils.random(60)); // We use LDAP password, but the password need to be set
                ldapUser.setActivated(true);
                try {
                    Attribute attribute = ctx.getAttributes().get("mail");
                    ldapUser.setEmail( attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
                    attribute = ctx.getAttributes().get("givenname");
                    ldapUser.setFirstName(attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
                    attribute = ctx.getAttributes().get("sn");
                    ldapUser.setLastName(attribute != null && attribute.size() > 0 ? (String) attribute.get(0) : "");
                } catch (NamingException e) {
                    log.warn("Couldn't get LDAP details for user: " + lowercaseLogonName);
                }

                Set<Authority> newUserAuthorities = new HashSet<>();
                Authority authority = authorityRepository.getOne(AuthoritiesConstants.USER);

                newUserAuthorities.add(authority); <-- This line in the Exception

                ldapUser.setAuthorities(newUserAuthorities);
                ldapUser.setLangKey("en");
                userRepository.saveAndFlush(ldapUser);

            }

Exception:

org.hibernate.LazyInitializationException: could not initialize proxy [com.app.my.let.domain.Authority#ROLE_USER] - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:155)
        at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:268)
        at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
        at com.app.my.let.domain.Authority_$$_jvst758_1e.hashCode(Authority_$$_jvst758_1e.java)
        at java.util.HashMap.hash(HashMap.java:339)
        at java.util.HashMap.put(HashMap.java:612)
        at java.util.HashSet.add(HashSet.java:220)
        at com.app.my.let.config.SecurityConfiguration$1.mapUserFromContext(SecurityConfiguration.java:249) <-- code line above

JPA properties:

jpa:
        database-platform: org.hibernate.dialect.SQLServer2012Dialect
        database: SQL_SERVER
        show_sql: true
        format_sql: true
        properties:
            hibernate.id.new_generator_mappings: true
            hibernate.cache.use_second_level_cache: false
            hibernate.cache.use_query_cache: false
            hibernate.generate_statistics: true

EDIT - This resolved my issue:

Optional<Authority> optAuthority = authorityRepository.findById(AuthoritiesConstants.USER);

Authority authority = optAuthority.get();
8
  • When are you opening your JPA session? Does AuthorityRepository open or close a session? Commented Feb 11, 2019 at 2:57
  • Pretty sure a session just gets opened when the app starts. There's never any code to openSession or getCurrentSession in either the old app (which works) or the new (doesn't). Added the jpa properties from the yml file up above. Commented Feb 11, 2019 at 3:06
  • Hibernate uses multiple sessions. It's bad practice to have one long-running session. I'm not familiar with JHipster specifically, but usually there is minimally one session per request and often multiple per complex request. Can you post the code of authorityRepository.getOne? You're adding the object to a hash set. The error most likely means that something you're using in your hashcode function is not being initialized by Hibernate before the session was closed. Does Authority have any associations? Commented Feb 11, 2019 at 3:15
  • It's a generic, empty class. package com.app.my.let.repository; import com.app.my.let.domain.Authority; import org.springframework.data.jpa.repository.JpaRepository; /** * Spring Data JPA repository for the Authority entity. */ public interface AuthorityRepository extends JpaRepository<Authority, String> { } Commented Feb 11, 2019 at 3:18
  • Then yes, that is closing the session stackoverflow.com/a/25710391/1245752. How is Authority.hashCode implemented? Commented Feb 11, 2019 at 3:21

1 Answer 1

5

This line:

Authority authority = authorityRepository.getOne(AuthoritiesConstants.USER);

gives you just the reference to an entity. Under the hood it calls EntityManager#getReference. As sais, this is not the entity, just the reference for object-relational mapping purposes. The exception is thrown, because you are trying to cast it outside of transactional environment.

There are couple of solutions. To get the entity, you would have to use EntityManager#find or do it within transaction (use @Transactional over the method). Here you could also call Hibernate.initialize(authority) to fetch the entity from database.

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, buried in the spec doc rather than the API doc... I actually solved it by just using findById().get(), which DOES fetch the actual data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.