Using StandardEditor as Process Form: IllegalArgumentException: entity is null

I’m using a StandardEditor for my process and everything is working fine, I can run the full process without any issue or any error.
The issue though is, when I try to start the process from the BProc menu:
BProc -> Start Process
Then select the very same process and click the “Start Process” button I get an the error: Entity is null:
Here is the error stack:

java.lang.IllegalArgumentException: entity is null
	at com.haulmont.bali.util.Preconditions.checkNotNullArgument(Preconditions.java:102)
	at com.haulmont.cuba.core.global.EntityStates.isNew(EntityStates.java:65)
	at com.haulmont.cuba.gui.screen.StandardEditor.setupEntityToEdit(StandardEditor.java:179)
	at com.company.travelreq.web.screens.travelrequest.TravelRequestEdit.setupEntityToEdit(TravelRequestEdit.java:98)
	at com.haulmont.cuba.gui.screen.StandardEditor.beforeShow(StandardEditor.java:104)
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170)
	at com.haulmont.cuba.gui.screen.Screen.fireEvent(Screen.java:128)
	at com.haulmont.cuba.gui.screen.UiControllerUtils.fireEvent(UiControllerUtils.java:60)
	at com.haulmont.cuba.web.sys.WebScreens.show(WebScreens.java:435)
	at com.haulmont.cuba.gui.screen.Screen.show(Screen.java:309)
	at com.haulmont.addon.bproc.web.screens.startprocess.StartProcessScreen.onProcessDefinitionsTableStartProcessActionPerformed(StartProcessScreen.java:58)
	at com.haulmont.bali.events.EventHub.publish(EventHub.java:170)
	at com.haulmont.cuba.gui.components.actions.BaseAction.actionPerform(BaseAction.java:221)
	at com.haulmont.cuba.web.gui.components.WebButton.buttonClicked(WebButton.java:64)
	at com.haulmont.cuba.web.widgets.CubaButton.fireClick(CubaButton.java:76)
	at com.vaadin.ui.Button$1.click(Button.java:57)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:153)
	at com.vaadin.server.ServerRpcManager.applyInvocation(ServerRpcManager.java:115)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocation(ServerRpcHandler.java:431)
	at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:396)
	at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:260)
	at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:82)
	at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:40)
	at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1577)
	at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:425)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:329)
	at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:215)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.springframework.web.filter.CompositeFilter$VirtualFilterChain.doFilter(CompositeFilter.java:107)
	at org.springframework.web.filter.CompositeFilter.doFilter(CompositeFilter.java:73)
	at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:93)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:834)

You mean that you defined the StandardEditor screen as a start process form in the modeler, right? If so, the did you look at this section in the documentation?

Yes , of course I did. I can start the process and with the here mentioned and assumed " Start process button", which is called differently in my code but of course working fine. As I said I can run the process perfectly fine starting it from the Entity Browser screen.

    public void onSubmitBtnClick() {
        TravelRequest travelRequest = getEditedEntity();
        travelRequest.setStatus(WorkflowStatus.AWAITING_APPROVER_ONE);
        Map<String, Object> processVariables = new HashMap<>();
        processVariables.put("travelRequest", travelRequest);
        commitChanges().then(() -> {
            bprocRuntimeService.startProcessInstanceByKey( "travelrequest", travelRequest.getStartDate() + ": " + travelRequest.getProjectNumber(), processVariables);
            System.out.println("Process Started?");
        }).then(() -> {
            close(null);
        });
    }

I am assuming though, that I also need to override the button that starts the process from the BProc menu, basically that should just open the StandardEditor Form for my Travelrequest, where the user then finds the Submit button which starts the process.

1 Like

In general case, the StandardEditor that is used for editing an entity cannot be used as a start process form. You may have one screen for editing the entity (you can have a “Start process” button inside the editor, of course), and to have a second screen, that is also an entity editor, but it is configured to be a start process form and it, for example, can display a limited number of entity fields - only those that are required for process start.
You can find an example of such a second screen in the bproc-sampler project. See the OrderEditStartForm.java there. Look at the code

    @Subscribe
    protected void onInit(InitEvent event) {
        Order order = metadata.create(Order.class);
        setEntityToEdit(order);
    }

It creates a new entity instance and set is an edited entity to the editor. That is probably what the standard editor doesn’t do.

Thanks Max,
whereas your explanation about having to create a second form for the start process isn’t correct, your code snippet helped me solve the issue.
I am using ONE StandardEditor form for everything, Creating the entity as well as for process handling: start process and task completions. My onInit() method now looks as follows, and the problem is hereby solved:

@ProcessVariable
    protected TravelRequest travelRequest;

 ....

@Subscribe
    protected void onInit(InitEvent event){
        if (travelRequest != null) {
            setEntityToEdit(travelRequest);
        } else {
            TravelRequest travelRequest = metadata.create( TravelRequest.class );
            setEntityToEdit(travelRequest);
        }
    }