Load Test Data at Server-Startup

Hi,

i’d like to add certain test data in the application at startup of the server. I got it working with creating init scripts of the db in the init folder. The content of the SQL files i extracted from the “System Information > Insert Script” popup of the entity inspector. As i said, it worked well, but it has some downsides:

  • The SQL statements are DBMS dependent
  • i have to copy the SQL files for every DBMS
  • i have to manually collect associations (like UserProfile, or UserRole)

Therefore i thought of the possibility to use the JSON export feature of the platform to achieve the same goal. I found the EntitiyImportExportService and the EntityImportExportAPI (btw. where is the difference between these interfaces?)
So my idea was to use the App.init method to load some JSON data with this service into the system at startup. Here’s an example code for the App.init:

 @Override
    protected void init() {
        super.init();
        EntityImportExportService importExportService = AppBeans.get(EntityImportExportService.class);
        Resources resources = AppBeans.get(Resources.class);
        Metadata metadata = AppBeans.get(Metadata.class);

        try {
            InputStream stream = resources.getResourceAsStream("test.zip");
            if (stream != null) {
                byte[] zipBytes = IOUtils.toByteArray(stream);
                EntityImportView entityImportView = createEntityImportView(metadata.getClass(Customer.class));
                importExportService.importEntities(zipBytes,entityImportView);
            }
            else {
                throw new RuntimeException("did not work");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    protected EntityImportView createEntityImportView(MetaClass metaClass) {
        EntityImportView entityImportView = new EntityImportView(metaClass.getJavaClass());
        for (MetaProperty metaProperty : metaClass.getProperties()) {
            switch (metaProperty.getType()) {
                case DATATYPE:
                case ENUM:
                    entityImportView.addProperty(metaProperty.getName());
                    break;
                case ASSOCIATION:
                case COMPOSITION:
                    if (!metaProperty.getRange().getCardinality().isMany()) {
                        entityImportView.addProperty(metaProperty.getName(), ReferenceImportBehaviour.IGNORE_MISSING);
                    }
                    break;
                default:
                    throw new IllegalStateException("unknown property type");
            }
        }
        return entityImportView;
    }

So here are my questions:

  • If i do this like above: i get a “java.lang.SecurityException: No security context bound to the current thread” - because there is no security context, so for now it unfortunately i doesn’t work
  • i have to copy the zip file into the confDir of the app application. But when i do this manually it will removed when i press the start button in studio (i hacked it by watching the directory and after it has been removed i quickly re-added it :smiley: ). So the question is, how can i automatically add these files. Can i do a gradle job that does that and if so, how can that be combined with studio?

Or do you have any other idea on how to automatically add DBMS independent data into the database at application startup?

Bye,
Mario

Hi Mario,

About EntitiyImportExportService and EntityImportExportAPI - the former is available on the client tier and actually delegates to the latter which is a middleware bean. This is a common approach for implementing business logic - you create a managed bean on the middleware (in this case with an interface), and if you need to invoke it from clients, you also create a service which is just a wrapper.

> to use the App.init method to load some JSON data with this service into the system at startup
The proper way to execute code on system startup is to use AppContext.Listener. The App.init() method is executed for each connected user, so it is certainly not what you need.

> java.lang.SecurityException: No security context bound to the current thread
In order to provide a security context to your code, use system authentication.

> i have to copy the zip file into the confDir of the app application
You can just pack it into the application JAR by placing it in the source tree. You will still be able to replace it in production with a file in conf directory if you need - the Resources bean provides this.

Hi Konstantin,

thanks for the information. For those who are interested, i created an example application that does the described functionality here: https://github.com/mariodavid/cuba-example-json-testdata/

Bye,
Mario