com.haulmont.cuba.core.global.RemoteException: --- java.lang.SecurityException: No security contex

Hi.

I’m getting the Exception
com.haulmont.cuba.core.global.RemoteException: java.lang.SecurityException: No security context bound to the current thread

when I’m trying to call a service’s method.

The method have a very simple code:


@Override
    public void updatePages(Issue issue, List<Page> pages) {
        try (Transaction tx = persistence.createTransaction()) {
            issue = persistence.getEntityManager().find(Issue.class, issue.getId());
            issue.setPages(pages);
            persistence.getEntityManager().persist(issue);
            tx.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Can you help me?

1 Like

Where do you call the service from?

From a controller of Web Module.

Screen controller? Or some Spring MVC controller?

Screen controller, of a custom screen.
My application’s objective is to administrate Magazine’s issues.
That screen is used to upload a PDF file, then the PDF file is processed and I create a list of Page object. I just want to set that list on Issue object (passed as a parameter for the screen) and save the Issue (then the pages must be automatic saved). First I tried to use DataManager, but I got the detached difficult. Then I tried to create a service and call it, but I got the SecurityException. Now I’m recreating all from zero. What do you think that is the best approach for my case?
Thank you.

Invoking a service from a screen controller and working with data via EntityManager is absolutely normal. Your code is correct except that you don’t need to call persistence.getEntityManager().persist(issue); because changes in managed objects are saved on transaction commit. But it has nothing to do with the security exception.
Could you provide the whole stack trace?

2016-04-12 12:04:39.808 ERROR [Thread-38] com.haulmont.cuba.core.sys.ServiceInterceptor - Exception: 
java.lang.SecurityException: No security context bound to the current thread
 at com.haulmont.cuba.core.sys.ServiceInterceptor.getUserSession(ServiceInterceptor.java:90) ~[cuba-core-6.1.2.jar:6.1.2]
 at com.haulmont.cuba.core.sys.ServiceInterceptor.aroundInvoke(ServiceInterceptor.java:70) ~[cuba-core-6.1.2.jar:6.1.2]
 at sun.reflect.GeneratedMethodAccessor86.invoke(Unknown Source) ~[na:na]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
 at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:621) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:610) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:68) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:168) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207) [spring-aop-4.2.0.RELEASE.jar:4.2.0.RELEASE]
 at com.sun.proxy.$Proxy148.updatePages(Unknown Source) [na:na]
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_60]
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_60]
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_60]
 at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_60]
 at com.haulmont.cuba.core.sys.remoting.LocalServiceInvokerImpl.invoke(LocalServiceInvokerImpl.java:86) [cuba-core-6.1.2.jar:6.1.2]
 at com.haulmont.cuba.web.sys.remoting.LocalServiceProxy$LocalServiceInvocationHandler.invoke(LocalServiceProxy.java:132) [cuba-web-6.1.2.jar:6.1.2]
 at com.sun.proxy.$Proxy44.updatePages(Unknown Source) [na:na]
 at net.gocoders.magazineappbackend.web.issue.IssueUploadPdf$1PDFWorker.run(IssueUploadPdf.java:165) [app-web-0.1-SNAPSHOT.jar:na]

The last line is interesting:
at net.gocoders.magazineappbackend.web.issue.IssueUploadPdf$1PDFWorker.run(IssueUploadPdf.java:165) [app-web-0.1-SNAPSHOT.jar:na]
I can guess that you invoke the service from a separate thread. If so, you should pass the security context to the new thread.
Use either background tasks (they set security context automatically) or pass it manually as explained here.

1 Like

Yes! That’s it! I’m back to the path. Tks.

And now I have a new difficult. =(

I’m trying to use CASCADE for delete Page’s when a Issue obj is deleted. I also want to use orphanRemoval. Nothing is working. Page’s are never removed.

Entities classes sources:


   /*
 * Copyright (c) 2016 MagazineAppBackend
 */
package net.gocoders.magazineappbackend.entity;

import javax.persistence.*;
import java.util.Date;

import com.haulmont.cuba.core.entity.StandardEntity;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.chile.core.annotations.Composition;
import com.haulmont.cuba.core.entity.annotation.OnDelete;
import com.haulmont.cuba.core.global.DeletePolicy;
import java.util.List;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.Versioned;
import com.haulmont.cuba.core.entity.Updatable;
import com.haulmont.cuba.core.entity.SoftDelete;

/**
 * @author arimolo
 */
@NamePattern("%s %s|issueNumber,issueDate")
@Table(name = "MAGAZINEAPPBACKEND_ISSUE")
@Entity(name = "magazineappbackend$Issue")
public class Issue extends BaseUuidEntity implements Versioned, Updatable, SoftDelete {
    private static final long serialVersionUID = 6829775742991251725L;

    @Column(name = "ISSUE_NUMBER", nullable = false)
    protected Integer issueNumber;

    @Temporal(TemporalType.DATE)
    @Column(name = "ISSUE_DATE", nullable = false)
    protected Date issueDate;

    @OrderBy("pageNumber")
    @OnDelete(DeletePolicy.CASCADE)
    @OneToMany(mappedBy = "issue", cascade = CascadeType.ALL, orphanRemoval = true)
    protected List<Page> pages;

    @Column(name = "COVER")
    protected String cover;

    @Version
    @Column(name = "VERSION", nullable = false)
    protected Integer version;

    @Column(name = "UPDATE_TS")
    protected Date updateTs;

    @Column(name = "UPDATED_BY", length = 50)
    protected String updatedBy;

    @Column(name = "DELETE_TS")
    protected Date deleteTs;

    @Column(name = "DELETED_BY", length = 50)
    protected String deletedBy;

    @Override
    public Boolean isDeleted() {
        return deleteTs != null;
    }

    @Override
    public void setDeletedBy(String deletedBy) {
        this.deletedBy = deletedBy;
    }

    @Override
    public String getDeletedBy() {
        return deletedBy;
    }

    @Override
    public void setDeleteTs(Date deleteTs) {
        this.deleteTs = deleteTs;
    }

    @Override
    public Date getDeleteTs() {
        return deleteTs;
    }


    @Override
    public void setUpdatedBy(String updatedBy) {
        this.updatedBy = updatedBy;
    }

    @Override
    public String getUpdatedBy() {
        return updatedBy;
    }

    @Override
    public void setUpdateTs(Date updateTs) {
        this.updateTs = updateTs;
    }

    @Override
    public Date getUpdateTs() {
        return updateTs;
    }


    @Override
    public void setVersion(Integer version) {
        this.version = version;
    }

    @Override
    public Integer getVersion() {
        return version;
    }


    public void setCover(String cover) {
        this.cover = cover;
    }

    public String getCover() {
        return cover;
    }


    public void setPages(List<Page> pages) {
        this.pages = pages;
    }

    public List<Page> getPages() {
        return pages;
    }


    public void setIssueNumber(Integer issueNumber) {
        this.issueNumber = issueNumber;
    }

    public Integer getIssueNumber() {
        return issueNumber;
    }

    public void setIssueDate(Date issueDate) {
        this.issueDate = issueDate;
    }

    public Date getIssueDate() {
        return issueDate;
    }
}

Page:


/*
 * Copyright (c) 2016 MagazineAppBackend
 */
package net.gocoders.magazineappbackend.entity;

import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Column;
import javax.persistence.Lob;
import com.haulmont.cuba.core.entity.StandardEntity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import com.haulmont.chile.core.annotations.NamePattern;
import com.haulmont.cuba.core.entity.BaseUuidEntity;
import com.haulmont.cuba.core.entity.Versioned;
import javax.persistence.Version;
import com.haulmont.cuba.core.entity.Updatable;
import java.util.Date;

/**
 * @author arimolo
 */
@NamePattern("%s %s|issue,pageNumber")
@Table(name = "MAGAZINEAPPBACKEND_PAGE")
@Entity(name = "magazineappbackend$Page")
public class Page extends BaseUuidEntity implements Versioned, Updatable {
    private static final long serialVersionUID = -8760048507768183964L;

    @Column(name = "PAGE_NUMBER", nullable = false)
    protected Integer pageNumber;

    @Lob
    @Column(name = "HTML_CONTENT")
    protected String htmlContent;

    @Lob
    @Column(name = "TEXT_CONTENT")
    protected String textContent;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ISSUE_ID")
    protected Issue issue;

    @Version
    @Column(name = "VERSION", nullable = false)
    protected Integer version;

    @Column(name = "UPDATE_TS")
    protected Date updateTs;

    @Column(name = "UPDATED_BY", length = 50)
    protected String updatedBy;

    @Override
    public void setUpdatedBy(String updatedBy) {
        this.updatedBy = updatedBy;
    }

    @Override
    public String getUpdatedBy() {
        return updatedBy;
    }

    @Override
    public void setUpdateTs(Date updateTs) {
        this.updateTs = updateTs;
    }

    @Override
    public Date getUpdateTs() {
        return updateTs;
    }


    @Override
    public void setVersion(Integer version) {
        this.version = version;
    }

    @Override
    public Integer getVersion() {
        return version;
    }


    public void setIssue(Issue issue) {
        this.issue = issue;
    }

    public Issue getIssue() {
        return issue;
    }


    public void setPageNumber(Integer pageNumber) {
        this.pageNumber = pageNumber;
    }

    public Integer getPageNumber() {
        return pageNumber;
    }

    public void setHtmlContent(String htmlContent) {
        this.htmlContent = htmlContent;
    }

    public String getHtmlContent() {
        return htmlContent;
    }

    public void setTextContent(String textContent) {
        this.textContent = textContent;
    }

    public String getTextContent() {
        return textContent;
    }
}

Thank you a lot! =)

Could you please start a separate topic?

Sure, I am so sorry.