Dynamic Datasource

Hello,
Here’s my question with an example:
User is presented with a screen where he can input parameters in the form. When the user clicks the OK button, it invokes a method called GetExtract().
This method returns data in a CSV format. Now, I need to get the CSV data and display it to the user in a table.
At first, I thought about creating an entity with fields, but I realized that the CSV data that is being returned will have different fields depending on the parameters. So this is not possible.
Then I thought, it would be great if when i get my CSV data, i could dynamically set the datasource to my table so that it displays the data. is it possible?
Or is it possible to have my code do: 1) read the CSV data, 2), create temporary (or transient) entity, 3) populate entity with data, 4) create datasource, and 5) set datasource to the table?
Thanks.

Creation of “temporary” entities is not possible at the moment. But this is a good idea and we will try to implement it for the next minor release.

Now you can fall back to Vaadin API and create a table with a dynamic set of columns with it. You should create an empty container (vbox) in your screen, unwrap it to get the underlying Vaadin container and then create a Vaadin table inside.

Thanks Konstantin, I will take a crack at it but I think it would be a great idea to show such an example in the CUBA sampler to show how to work with Vaadin container.

Hello, I’m trying to follow the example in the manual, but in the Edit screen controller, it doesn’t let me reference com.vaadin.ui, so I can’t unwrap it.
Can you show me an example with xml and controller on how to dynamically create a table with one row?
I also tried to use the WebCompanion stuff but it doesn’t work.
Thanks.

Hi Francis

I’m guessing that your screen controller is located within Gui application module. You can’t reference Vaadin stuff from there because the code written in Gui module is generic part of the UI and could potentially be used in Desktop module as well. Client-specific logic can only be placed inside client module (Web or Desktop).

If you 100% that you aren’t going to use Desktop client in your application then you could simply move your screen from Gui module to the Web module. You will be able to unwrap components into their Vaadin implementation then.

Another option is to use Companions and perform client-specific login inside them. Perhaps you could tell us what problems did you have with WebCompanion and we would help you out with them.

Thanks Igor for the response. Yes, my screen controller is located within the GUI module.
Basically, here’s what I’m doing: In my XML, I created a vbox:

  
<vbox id="tabularBox"   
                              spacing="true"> 
</vbox>   

In my controller I have this:

 
public class MigrationReportEdit extends AbstractEditor<MigrationReport> {   
    public interface Companion {   
        void initBox(GroupBoxLayout boxLayout);   
    }   
    @Inject private GroupBoxLayout tabularBox;   
    @Inject protected Companion companion;   


In my init method of the controller, I have this:


@Override   
    public void init(Map<String,Object> params) {   
        companion.initBox(tabularBox);   


I created a Java class file called WebMigrationReportEditCompanion.java where I have the following code:


public class WebMigrationReportEditCompanion implements MigrationReportEdit.Companion {   
    @Override   
    public void initBox(GroupBoxLayout groupBoxLayout) {   
        com.vaadin.ui.Layout layout = (com.vaadin.ui.Layout) WebComponentsHelper.unwrap(groupBoxLayout);   
        com.vaadin.ui.Table table = new com.vaadin.ui.Table();   
        // Define two columns for the built-in container   
        table.addContainerProperty("Investment", String.class, null);   
        table.addContainerProperty("Description",  String.class, null);   
        table.addItem(new Object[]{"ABC","Hello"});   
        layout.addComponent(table);   
    }   
}  

As you can see, all I’m trying to do is populate the vbox layout with a table containing one row.
Am I doing anything wrong?
Oh and by the way, when I launch the application and try to go to the screen, I get the following error message:

17:00:07.231 ERROR com.haulmont.cuba.web.log.AppLog - Exception in com.haulmont.cuba.web.gui.components.WebTable$1:   
java.lang.StringIndexOutOfBoundsException: String index out of range: -1   
        at java.lang.String.substring(String.java:1967)   
        at com.haulmont.cuba.core.sys.javacl.SourcesAndDependencies.collectDependencies(SourcesAndDependencies.java:43)   
        at com.haulmont.cuba.core.sys.javacl.JavaClassLoader.loadClass(JavaClassLoader.java:151)   
        at java.lang.ClassLoader.loadClass(ClassLoader.java:411)   
        at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:677)   
        at com.haulmont.cuba.core.sys.AbstractScripting$CubaGroovyClassLoader.loadClass(AbstractScripting.java:440)   
        at groovy.lang.GroovyClassLoader.loadClass(GroovyClassLoader.java:545)   
        at com.haulmont.cuba.core.sys.AbstractScripting.loadClassNN(AbstractScripting.java:266)   
        at com.haulmont.cuba.gui.WindowManager.initCompanion(WindowManager.java:743)   
        at com.haulmont.cuba.gui.WindowManager.initWrapperFrame(WindowManager.java:706)   
        at com.haulmont.cuba.gui.WindowManager.createWindow(WindowManager.java:176)   
        at com.haulmont.cuba.gui.WindowManager.openEditor(WindowManager.java:454)   
        at com.haulmont.cuba.gui.components.WindowDelegate.openEditor(WindowDelegate.java:220)   
        at com.haulmont.cuba.web.gui.WebWindow.openEditor(WebWindow.java:393)   
        at com.haulmont.cuba.gui.components.actions.EditAction.internalOpenEditor(EditAction.java:182)   
        at com.haulmont.cuba.gui.components.actions.EditAction.actionPerform(EditAction.java:175)   
        at com.haulmont.cuba.web.gui.components.WebAbstractTable.handleClickAction(WebAbstractTable.java:640)   
        at com.haulmont.cuba.web.gui.components.WebAbstractTable.lambda$initComponent$4fd149ee$1(WebAbstractTable.java:535)   
        at sun.reflect.GeneratedMethodAccessor130.invoke(Unknown Source)   
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)   
        at java.lang.reflect.Method.invoke(Method.java:497)   
        at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:508)   
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:198)   
        at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)   
        at com.vaadin.server.AbstractClientConnector.fireEvent(AbstractClientConnector.java:1003)   
        at com.vaadin.ui.Table.handleClickEvent(Table.java:3180)   
        at com.vaadin.ui.Table.changeVariables(Table.java:2956)   
        at com.haulmont.cuba.web.toolkit.ui.CubaTable.changeVariables(CubaTable.java:208)   
        at com.vaadin.server.communication.ServerRpcHandler.changeVariables(ServerRpcHandler.java:508)   
        at com.vaadin.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:327)   
        at com.vaadin.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:202)   
        at com.vaadin.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:95)   
        at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.lambda$synchronizedHandleRequest$65(CubaVaadinServletService.java:281)   
        at com.haulmont.cuba.web.sys.CubaVaadinServletService.withUserSession(CubaVaadinServletService.java:171)   
        at com.haulmont.cuba.web.sys.CubaVaadinServletService$CubaUidlRequestHandler.synchronizedHandleRequest(CubaVaadinServletService.java:281)   
        at com.vaadin.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:41)   
        at com.vaadin.server.VaadinService.handleRequest(VaadinService.java:1408)   
        at com.vaadin.server.VaadinServlet.service(VaadinServlet.java:356)   
        at com.haulmont.cuba.web.sys.CubaApplicationServlet.serviceAppRequest(CubaApplicationServlet.java:226)   
        at com.haulmont.cuba.web.sys.CubaApplicationServlet.service(CubaApplicationServlet.java:149)   
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)   
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291)   
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)   
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)   
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)   
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)   
        at com.haulmont.cuba.web.sys.CubaHttpFilter.handleNotFiltered(CubaHttpFilter.java:100)   
        at com.haulmont.cuba.web.sys.CubaHttpFilter.doFilter(CubaHttpFilter.java:87)   
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239)   
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)   
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219)   
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)   
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)   
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142)   
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)   
        at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)   
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)   
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518)   
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091)   
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:673)   
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1526)   
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1482)   
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)   
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)   
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)   
        at java.lang.Thread.run(Thread.java:745)  

Hello Francis,

Could you please move your classes to some package (e.g. com.organization.etc …), and try again?

The issues caused by our dynamic compilation mechanism, which expects that class should always be in some package.

Will be fixed in next release.

when I moved my WebMigrationReportEditCompanion.java to a package, I get the following error now:
IllegalArgumentException: Can not set com.haulmont.cuba.gui.components.GroupBoxLayout field com.company.flux.gui.migrationreport.MigrationReportEdit.tabularBox to com.haulmont.cuba.web.gui.components.WebVBoxLayout

Hi Francis
you have declared your tabularBox as “vbox” in screen xml which is VerticalBox component.
However in your screen controller and companion you’ve change its type to GroupBox.
You should fix either xml or Java code to use the same component type

Thanks Igor, I changed the XML to be groupbox and now I’m getting this error:
ClassCastException: com.haulmont.cuba.web.toolkit.ui.CubaGroupBox cannot be cast to com.vaadin.ui.Layout

Francis, GroupBox is a composite component: it contains panel which in turn contains either Vertical or Horizontal layout
so, you need to unwrap GroupBox into Panel and then add your table into Panel’s layout. Try to use this code:


public class WebMigrationReportEditCompanion implements MigrationReportEdit.Companion {    
    @Override    
    public void initBox(GroupBoxLayout groupBoxLayout) {    
        com.vaadin.ui.Panel panel = (com.vaadin.ui.Panel) WebComponentsHelper.unwrap(groupBoxLayout);    
        com.vaadin.ui.Table table = new com.vaadin.ui.Table();    
        // Define two columns for the built-in container    
        table.addContainerProperty("Investment", String.class, null);    
        table.addContainerProperty("Description",  String.class, null);    
        table.addItem(new Object[]{"ABC","Hello"});    
        ((com.vaadin.ui.Layout) panel.getContent()).addComponent(table);    
    }    
}   

hope it helps

It worked this time. Thanks so much Igor. It was very helpful.

Hi,
the problem is fixed in the platform version 6.1.2.