Creating two related entities using one transaction - Null

Hi all,

I have two entities: Project and Page. With a One to Many / Many to One relationship respectively (only relevant parts of the code are shown)

Project

@Entity
public class Project extends BaseIdentityIdEntity {

@Column(name = "NAME", nullable = false)
protected String name;

@OneToMany(mappedBy = "project")
protected List<Page> pages;

public List<Page> getPages() {
    if(pages != null){
        return Collections.unmodifiableList(pages);
    }
    return null;
}

public void addNewPage(Page page){
    pages.add(page);
}

}

Page

@Entity
public class Page extends BaseIdentityIdEntity {
    private static final long serialVersionUID = 1472149496370934955L;

    @Column(name = "NAME", nullable = false)
    protected String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "PROJECT_ID")
    protected Project project;

 (...)
}

After creating the Project i need to use its id to create a Page. I am using a Transaction for that but I am getting null value for Project id when I set a page. Here is the code of the Transaction below:

@Override
public Project createProject(Project project) {

    Transaction tx = persistence.createTransaction();
    try{
        EntityManager em = persistence.getEntityManager();
        project.setPublicProject(true);
        project.setPublished(false);
        em.persist(project);

        Page page = metadata.create(Page.class);
        page.setName("index");
        page.setTheme("yeti");
        page.setProject(project);
        em.persist(page);
        project.addNewPage(page);
        em.persist(project);
        
        tx.commit();

    } finally {
        tx.end();
    }

    return project;

}

Is it the right way of doing this ?

Thanks in advance

James

Hi James,

The way you create entities looks correct except one extra closing bracket and the second em.persist(project) which are probably remains of a deleted code.

The reason why you don’t see IDs of entities after their creation is that they are BaseIdentityIdEntity - based on Identity PK, so they get identifiers only after inserting into the database, i.e. after the transaction commit. Does it cause any problems?

Hi Konstantin,

You are right. That bracket was not supposed to be there. I edited and removed.

When I run this code I get an NullPointerException in this line

project.addNewPage(page);

I think that happens maybe because of the lack of the id in project object. So, what would be the best thing to do in this case ?

This is the exception full trace

java.lang.NullPointerException: null
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
	org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
	org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
	org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:114)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	com.haulmont.restapi.auth.CubaAnonymousAuthenticationFilter.doFilter(CubaAnonymousAuthenticationFilter.java:66)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter.doFilter(OAuth2AuthenticationProcessingFilter.java:176)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:96)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
	org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
	org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
	org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
	org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
	com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:108)
	com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:95)
</pre><p><b>Root Cause</b></p><pre>com.haulmont.cuba.core.global.RemoteException:

Thanks for the reply

Could you provide the full stack trace? I don’t see the line of code caused the exception.

I have fixed the NullPointer error in my Project class.

public void addNewPage(Page page){
    if(pages == null){
        pages = new ArrayList<>();
    }
    pages.add(page);
}

But after the transaction finishes the Project is created but the Page not. What am I missing here ?

Thank you

Could you check in the database if Page is not created at all or it is created but has no correct reference to Project?

You were right. After cleaning the database and running it again the new Page was there. But it seems has incorrect reference to the project. I will investigate more and get it back to you in this same topic.

Thank you

Everything worked. Thank you