0

I'm using JSF, spring boot, and spring data for my project. I'm trying to edit an existing object. To do that, I'm passing the object id as a parameter to a view and then specifying f:viewAction that looks in the database and loads the object. What I'm getting is a "could not initialize proxy .. no Session" Lazyloadexception later on, in a different method, when calling a simple getter on that SAME object (the same object that I got by id, not an object inside a collection or anything).

I've tried:

  • putting @Transactional on both the JSF bean class AND the DAO classes
  • putting @Transactional on both the onload method called from f:viewAction and the getter method for the object.
  • putting spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true in my application.properties (yes, I know, anti-pattern, but a working application using an antipattern is better than an application that doesn't work at all. Regardless, it did nothing)
  • putting @EnableTransactionManagement on the setup class that extends SpringBootServletInitializer
  • putting @EnableTransactionManagement on the PersistenceConfig class

Basically, every "solution" that I could find after hours and hours of googling this error. I'm not sure what to do at this point. I have a feeling this has something to do with the load order and the DAO call being in the f:viewAction method. Maybe that uses a different session that anything that accesses the object via methods?

Sorry for including a lot of parts, I just don't know where the root cause lies. I'm suspecting it's the interplay of spring data, JPA, and JSF somewhere.

I've had the same error when I tried doing the database call to initialize objects in a method with a @PostConstruct annotation. The way I "solved" (read: patched) it was to do the database call inside of the getter, which is dumb ( if(myobject == null) do the db call. else return myobject)

Error:

org.hibernate.LazyInitializationException: could not initialize proxy [mypackage.recipe.RecipeItem#8] - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
    at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
    at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
    at mypackage.recipe.RecipeItem$HibernateProxy$G4ytmgbe.getDisplayName(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)


@EnableJpaRepositories(basePackages = "mypackage")
@EnableTransactionManagement
public class PersistenceConfig
{
    // nothing here
}

@SpringBootApplication(scanBasePackages={"mypackage"})
@EnableJpaRepositories(basePackages = "mypackage")
@EnableTransactionManagement
public class SpringBootTomcatApplication extends SpringBootServletInitializer {
    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter bean = new HibernateJpaVendorAdapter();
        bean.setDatabase(Database.MYSQL);
        bean.setGenerateDdl(true);
        bean.setShowSql(true);
        return bean;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,
            JpaVendorAdapter jpaVendorAdapter) {
        LocalContainerEntityManagerFactoryBean bean = new LocalContainerEntityManagerFactoryBean();
        bean.setDataSource(dataSource);
        bean.setJpaVendorAdapter(jpaVendorAdapter);
        bean.setPackagesToScan("mypackage");
        return bean;
    }

    @Bean
    public JpaTransactionManager transactionManager(EntityManagerFactory emf) {
        return new JpaTransactionManager(emf);
    }
}

@Component
@Transactional
@Scope("session")
public class EditRecipeItemControllerBean extends RecipeItemControllerBean
{
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @Transactional
    public void onload() {
        Map<String,String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        String recipeId = params.get("recipeId");
        log.info("from context recipe id: " + recipeId);
        //TODO error handling
        setRecipe(recipeDao.getOne(Long.valueOf(recipeId)));
    }

    public void submit() {
        super.save();
    }
}       

public class RecipeItemControllerBean implements Serializable
{    
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Autowired
    AuthenticationFacade authenticationFacade;  
    @Autowired
    RecipeItemDao recipeDao;

    private RecipeItem recipe;

    /**
     * @return the recipe
     */
    public RecipeItem getRecipe()
    {
        return recipe;
    }

    /**
     * @param recipe the recipe to set
     */
    public void setRecipe(RecipeItem recipe)
    {
        this.recipe = recipe;
    }

    public void save() {
        log.debug("Saving recipe: " + recipe);
        recipeDao.save(recipe);
    }
}

@Entity
@Table(name = "recipe_item")
@NamedQueries(
{
    // a bunch of named queries here
})
public class RecipeItem extends ClientSpecific
{
    @Column(length = 256)
    private String description;
    @Lob
    @Column(name = "full_info", length = 65535)
    private String fullInfo;
    @Column(name = "thumbnail_uri", length = 1024)
    private String thumbnailUri;
    @Lob
    @Column(name = "preparation_instructions", length = 65535)
    private String preparationInstructions;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "recipeItem", fetch = FetchType.EAGER)
    private Collection<RecipeItemIngredients> recipeItemIngredients;

    public RecipeItem()
    {
    }

    //getters and setters 
}

@MappedSuperclass
public abstract class ClientSpecific extends NamedBaseEntity
{    
    @JoinColumn(name = "client_id", referencedColumnName = "id")
    @ManyToOne
    private Client client;

    public ClientSpecific()
    {
    }

    public ClientSpecific(Long id)
    {
        super(id);
    }

    public ClientSpecific(Long id, Client client)
    {
        super(id);
        this.client = client;
    }

    // getters and setters clipped for brevity
}

@MappedSuperclass
public abstract class NamedBaseEntity extends BaseEntity
{
    @Size(max = 64)
    @Column(name = "display_name")
    private String displayName;

    public NamedBaseEntity()
    {
    }

    public NamedBaseEntity(Long id)
    {
        super(id);
    }
    // gettes setters and tostring
}

@MappedSuperclass
@JsonIgnoreProperties(value = {"updated", "created"})
public abstract class BaseEntity implements Serializable
{    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;

    @Column(name = "updated")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updated;

    @Column(name = "active")
    private Short active = (short) 1;

    public BaseEntity()
    {
    }

    public BaseEntity(Long id)
    {
        this.id = id;
    }
    // getters, settes, toString, hascode and equals
}

@Repository
@Transactional
@Component
public interface RecipeItemDao extends JpaRepository<RecipeItem, Long>
{
    // methods and implementation auto-generated by Spring Data
}

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>mypackage.web</groupId>
    <artifactId>CoffeeShopWebApp</artifactId>
    <version>0</version>
    <packaging>war</packaging>

    <name>CoffeeShopWebApp</name>

    <properties>
        <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.1.2.RELEASE</version>
            <exclusions>
                <exclusion>
                    <groupId>org.hibernate.validator</groupId>
                    <artifactId>hibernate-validator</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mypackage.base</groupId>
            <artifactId>myapplication-module-base</artifactId>
            <version>0</version>
        </dependency>
        <dependency>
            <groupId>org.joinfaces</groupId>
            <artifactId>joinfaces-dependencies</artifactId>
            <version>4.0.2</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.primefaces</groupId>
            <artifactId>primefaces</artifactId>
            <version>6.2</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.extensions</groupId>
            <artifactId>primefaces-extensions</artifactId>
            <version>6.2.10</version>
        </dependency>
        <dependency>
            <groupId>org.primefaces.extensions</groupId>
            <artifactId>resources-ckeditor</artifactId>
            <version>6.2.10</version>
        </dependency>
        <dependency>
            <groupId>${project.groupId}</groupId>
            <artifactId>myapplication-recipe</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <compilerArguments>
                        <endorseddirs>${endorsed.dir}</endorseddirs>
                    </compilerArguments>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <phase>validate</phase>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>${endorsed.dir}</outputDirectory>
                            <silent>true</silent>
                            <artifactItems>
                                <artifactItem>
                                    <groupId>javax</groupId>
                                    <artifactId>javaee-endorsed-api</artifactId>
                                    <version>7.0</version>
                                    <type>jar</type>
                                </artifactItem>
                            </artifactItems>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

spring.datasource.url=jdbc:mysql://myDatabaseStuff?zeroDateTimeBehavior=convertToNull
spring.datasource.username=censored
spring.datasource.password=censored
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.jmx.default-domain: censored
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.hibernate.ddl-auto=none
server.error.whitelabel.enabled=false
Mohit Kanwar
  • 2,962
  • 7
  • 39
  • 59
Creature
  • 994
  • 1
  • 12
  • 27
  • Great you found the solution, but please next time try creating a [mcve]. Noone is able (or going to) help with a questions that contains such an extensive amount of code. – Kukeltje Mar 27 '19 at 12:14
  • That was as minimum as I could get it, since I had no idea where the problem lay. It could have been with any of the properties, weird includes in the POM, the fact that the entities inherited from MappedSuperclass instead of having all hte info in one class, persistence config, how I had the setup, etc. Insead of something as simple as "getOne()" method. – Creature Apr 02 '19 at 04:12
  • All the more reason to create a [mcve]: To narrow things down – Kukeltje Apr 02 '19 at 06:24

1 Answers1

1

I figured it out. It wasn't any of my transactional stuff, like I thought it was. It was the fact that I was using getOne() instead of findById().

This is the question/answer that helped me:

spring data jpa getOne throw LazyInitializationException and findBy not

Creature
  • 994
  • 1
  • 12
  • 27