Giter Club home page Giter Club logo

bootique-cayenne's Introduction

build test deploy Maven Central

Bootique is a minimally opinionated java launcher and integration technology. It is intended for building container-less runnable Java applications. With Bootique you can create REST services, webapps, jobs, DB migration tasks, etc. and run them as if they were simple commands. No JavaEE container required! Among other things Bootique is an ideal platform for Java microservices, as it allows you to create a fully-functional app with minimal setup.

Each Bootique app is a collection of modules interacting with each other via dependency injection. This GitHub project provides Bootique core. Bootique team also develops a number of important modules. A full list is available here.

Quick Links

Support

You have two options:

  • Open an issue on GitHub with a label of "help wanted" or "question" (or "bug" if you think you found a bug).
  • Post a question on the Bootique forum.

TL;DR

For the impatient, here is how to get started with Bootique:

  • Declare the official module collection:
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>io.bootique.bom</groupId>
            <artifactId>bootique-bom</artifactId>
            <version>3.0-M4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency> 
    </dependencies>
</dependencyManagement>
  • Include the modules that you need:
<dependencies>
    <dependency>
        <groupId>io.bootique.jersey</groupId>
        <artifactId>bootique-jersey</artifactId>
    </dependency>
    <dependency>
        <groupId>io.bootique.logback</groupId>
        <artifactId>bootique-logback</artifactId>
    </dependency>
</dependencies>
  • Write your app:
package com.foo;

import io.bootique.Bootique;

public class Application {
    public static void main(String[] args) {
        Bootique
            .app(args)
            .autoLoadModules()
            .exec()
            .exit();
    }
}

It has main() method, so you can run it!

For a more detailed tutorial proceed to this link.

Upgrading

See the "maven-central" badge above for the current production version of bootique-bom. When upgrading, don't forget to check upgrade notes specific to your version.

bootique-cayenne's People

Contributors

aarrsseni avatar andrus avatar atomashpolskiy avatar const1993 avatar elena-bondareva avatar irus avatar kravchenkoas avatar stariy95 avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bootique-cayenne's Issues

bootique-cayenne-test

Create a test setup for Cayenne that expands bootique-jdbc-test with facilities to bootstrap test schema from Cayenne model. Does not require any bootstrap beyond (auto)loading of bootique-cayenne-test

Pure Bootique bootstrap of Cayenne projects

Currently bootique-cayenne would support either pure Cayenne projects with DataNodes configured in cayenne-project.xml or single DataNode projects configured via Bootique. So a fairly common multi-DataNode projects that would previously use JNDI DataSource can not be configured in Bootique.

One idea is to allow (optionally) to completely ignore cayenne-project.xml in Bootique and connect DataMaps to DataSources straight in the YAML. E.g.:

cayenne
  # default DataSource
  datasource: myds

  # current config - implicit classpath URLs
  configs:
    - cayenne-project.xml

  # maps config ... supports DataMap XML references in ResourceFactory format
  maps:
    - map: http://example.org/mymap1.map.xml
      datasource: myds1
    - map: classpath:mymap2.map.xml
      datasource: myds2
      # uses default DataSource
    - map: mymap3.map.xml 

bootique-cayenne-test presence breaks BQModuleProviderChecker.testMetadata

Whenever a module has bootique-cayenne-test as one of the test dependencies, it can not execute BQModuleProviderChecker.testMetadata test, as Cayenne stack gets eagerly initialized and the following exception is thrown:

1) Error injecting constructor, org.apache.cayenne.configuration.server.DataDomainLoadException: [v.4.0.M5 Feb 24 2017 07:47:55] DataDomain startup failed: No DataSources are available for Cayenne. Add a DataSource via 'bootique-jdbc' or map it in Cayenne project.
  at io.bootique.cayenne.test.CayenneTestModule$SchemaLoader.<init>(CayenneTestModule.java:53)
  at io.bootique.cayenne.test.CayenneTestModule.configure(CayenneTestModule.java:34)
  while locating io.bootique.cayenne.test.CayenneTestModule$SchemaLoader

Upgrade for Cayenne 4.0.M4

Once 4.0.M4 of Cayenne becomes official, we need to upgrade bootique-cayenne. Specifically there is an incompatibility in injection of SchemaUpdateStrategy (new Cayenne requires SchemaUpdateStrategyFactory injection instead - see Cayenne upgrade notes)

Implicit config should not be loaded when there is an explicit Bootique config of maps

Given a project with default name cayenne-project.xml and the following YAML config, we get an error similar to the one below. It happens because Cayenne loads each DataMap twice - once via implicit default project, and the second time - based on the "maps" section.

We should ignore the default project if maps are present explicitly (perhaps with a warning in the logs).

cayenne:
  createSchema: true
  maps:
    - location: classpath:dm1.map.xml
      name: map1
      datasource: ds1
    - location: classpath:dm2.map.xml
      name: map2
      datasource: ds2

Error:

org.apache.cayenne.CayenneRuntimeException: [v.4.0.RC1 Apr 18 2018 13:10:58] Can't perform lookup. There is more than one ObjEntity mapped to io.bootique.cayenne.dm1.Entity1

	at org.apache.cayenne.map.MappingCache.getObjEntity(MappingCache.java:175)
	at org.apache.cayenne.map.ProxiedMappingNamespace.getObjEntity(ProxiedMappingNamespace.java:73)
	at org.apache.cayenne.map.EntityResolver.getObjEntity(EntityResolver.java:494)
	at org.apache.cayenne.access.DataContext.newObject(DataContext.java:469)

Exception when referencing CayenneModule by class

If CayenneModule is loaded without using the builder, e.g.:

Bootique.app(new String[0]).module(CayenneModule.class);

Bootique generates access exception:

java.lang.RuntimeException: Error instantiating Module of type: com.nhl.bootique.cayenne.CayenneModule
    at com.nhl.bootique.Bootique.createModule(Bootique.java:47)
    at com.nhl.bootique.Bootique.lambda$module$5(Bootique.java:108)
    at com.nhl.bootique.Bootique$$Lambda$4/1018937824.module(Unknown Source)
    at com.nhl.bootique.ModuleMerger.lambda$toNodeMap$15(ModuleMerger.java:40)
    at com.nhl.bootique.ModuleMerger$$Lambda$6/653687670.accept(Unknown Source)
    at java.util.ArrayList.forEach(ArrayList.java:1234)
    at com.nhl.bootique.ModuleMerger.toNodeMap(ModuleMerger.java:38)
    at com.nhl.bootique.ModuleMerger.getModules(ModuleMerger.java:26)
    at com.nhl.bootique.Bootique.createInjector(Bootique.java:348)
    at com.nhl.bootique.Bootique.createRuntime(Bootique.java:264)
    at com.nhl.bootique.test.BQTestRuntime.createRuntime(BQTestRuntime.java:43)
    at com.nhl.bootique.test.BQDaemonTestRuntime.start(BQDaemonTestRuntime.java:75)
    at com.nhl.bootique.test.BQDaemonTestRuntime.start(BQDaemonTestRuntime.java:37)
Caused by: java.lang.IllegalAccessException: Class com.nhl.bootique.Bootique can not access a member of class com.nhl.bootique.cayenne.CayenneModule with modifiers ""
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101)
    at java.lang.Class.newInstance(Class.java:427)
    at com.nhl.bootique.Bootique.createModule(Bootique.java:45)
    ... 29 more

Need to make no-arg constructor public.

Support for join tables in CayenneTestDataManager

Need a way to setup and access Table object for flattened join tables in CayenneTestDataManager. Perhaps in addition to declaring tables by entity class, allow declarations and lookup by class and flattened relationship (String or Property) ?

bootique-cayenne-test: test tables are not committed with rollbackOnReturn=true and defaultAutoCommit=false

With the following test data source settings:

jdbc:
  ds:
    url: jdbc:derby:target/derby/derby3;create=true
    initialSize: 1
    rollbackOnReturn: true
    defaultAutoCommit: false

created test schema is rolled back and is not visible to the operations that follow:

CayenneTestDataManager dataManager = new CayenneTestDataManager(runtime, false, Table1.class);
Table t1 = dataManager.getTable(Table1.class);
assertEquals(0, t1.getRowCount());
[main] INFO io.bootique.jdbc.test.DefaultDatabaseChannel - SELECT COUNT(*) FROM "table1"
Stopping all JVM Derby servers...

java.lang.RuntimeException: Error running SQL: SELECT COUNT(*) FROM "table1"

	at io.bootique.jdbc.test.DefaultDatabaseChannel.select(DefaultDatabaseChannel.java:51)
	at io.bootique.jdbc.test.Table.selectOne(Table.java:192)
	at io.bootique.jdbc.test.Table.getRowCount(Table.java:293)
	at io.bootique.cayenne.test.CayenneTestDataManagerTxIT.testDataSourceDoesNotAutocommit(CayenneTestDataManagerTxIT.java:27)
...
Caused by: java.sql.SQLSyntaxErrorException: Table/View 'table1' does not exist.
	at org.apache.derby.impl.jdbc.SQLExceptionFactory.getSQLException(Unknown Source)

Test API: smart DB cleanup - handle dependent tables

CayenneDataManager should be smart enough to delete data from tables related to the tables it contains. This would allow to build data managers using a subset of a bigger Cayenne model without worrying about data leftovers from other tests.

Contributing Cayenne projects via DI

Similar to the analogous Liquibase feature it would be nice for the modules to be able to contribute Cayenne projects to runtime via DI. Cayenne project location within a given module is almost invariably fixed and known to the module. So the final app doesn't need to worry about declaring all participating projects in the YAML.

There are some concerns about ordering, just like with Liquibase. So the suggested implementation would skip all contributed projects if "cayenne.configs" key is defined in YAML.

Make project-less ServerRuntime possible

Sometimes we want an empty Cayenne stack... Nothing wrong with that, the app should not fail. Currently it does:

Caused by: org.apache.cayenne.configuration.server.DataDomainLoadException: [v.4.0.M3 Feb 08 2016 16:38:05] Configuration resource "cayenne-project.xml" is not found.
    at org.apache.cayenne.configuration.server.DataDomainProvider.descriptorFromConfigs(DataDomainProvider.java:198)
    at org.apache.cayenne.configuration.server.DataDomainProvider.createAndInitDataDomain(DataDomainProvider.java:110)

Perhaps on bq-cayenne side we set the default dynamically. If "cayenne-project.xml" is present on classpath, we use that. If not, we revert to project-less stack (with a note in the logs).

Adding Shutdown hook

Bootique supports a shutdown hook since 0.11. Let's add a Cayenne-specific hook that would shutdown ServerRuntime. Of course this requires an upgrade to BQ 0.11.

Support for contributing multiple projects to a single runtime

Currently CayenneModule does not support loading multiple Cayenne configs into a single ServerRuntime. Add another YAML key to support that:

cayenne:
  config: c1.xml # this exists now
  configs: # new
    - c2.xml
    - c3.xml

Configs specified the new and the old way will be merged together.. And I guess we can deprecate "config" key and print a warning when it is found in the YAML

Provide details on startup failure when Cayenne project has non-default name

Exception is thrown under the conditions:

  1. Cayenne project has non-default name
  2. YAML config is empty
  3. Data node is declared in Cayenne project

Current trace:

Caused by: java.lang.IllegalStateException: No DataSources are available for Cayenne. Add a DataSource via 'bootique-jdbc' or map it in Cayenne project.
	at io.bootique.cayenne.BQCayenneDataSourceFactory.throwOnNoDataSource(BQCayenneDataSourceFactory.java:56)

New module: bootique-cayenne-jcache

Integrate Cayenne caching with brand new bootique-jache. This will ensure smooth declarative Cayenne integration with JCache providers such as EhCache. QueryCacheProvider should actually go to Cayenne eventually.

Use single bootique-jdbc datasource as the default for Cayenne

Most apps have a single DataSource. So no need for explicit Cayenne configuration (datasource: xyz) in this case. Also if we forget to map the DataSource, we get a confusing error:

org.apache.cayenne.CayenneRuntimeException: [v.4.0.M3 Feb 08 2016 16:38:05] No default DataNode exists.
    at org.apache.cayenne.access.DataDomainQueryAction.engineForName(DataDomainQueryAction.java:535)
    at org.apache.cayenne.query.SQLTemplate.route(SQLTemplate.java:134)
    at org.apache.cayenne.query.IndirectQuery.route(IndirectQuery.java:92)
    at org.apache.cayenne.access.DataDomainQueryAction.runQuery(DataDomainQueryAction.java:432)

Bad DataSource mapping results in an obscure Cayenne DI NPE

If say we don't have a default DataSource and there's more than one DS available in the runtime, the error that we get is completely obscure (see below), as it happens when a null string is bound to Cayenne DI. Let's make sure we throw something explicit and useful for debugging.

     Exception: java.lang.NullPointerException
        Message: 

  Stack trace:

  - org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
  - org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
  - org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:105)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
  - org.apache.cayenne.di.spi.CustomProvidersProvider.get(CustomProvidersProvider.java:39)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:43)
  - org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
  - org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:139)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.value(FieldInjectingProvider.java:105)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.injectMember(FieldInjectingProvider.java:68)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.injectMembers(FieldInjectingProvider.java:59)
  - org.apache.cayenne.di.spi.FieldInjectingProvider.get(FieldInjectingProvider.java:44)
  - org.apache.cayenne.di.spi.DefaultScopeProvider.get(DefaultScopeProvider.java:50)
  - org.apache.cayenne.di.spi.DefaultInjector.getInstance(DefaultInjector.java:134)
  - org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:134)```

Use ResourceFactory URL format for configs

Per #15 we will start to specify DataMap resources in ResourceFactory URL format. We need a symmetrical approach to the main project configs (cayenne-project.xml files). So perhaps we deprecate "configs:" key that implicitly uses "classpath:" URLs, replacing it with a new "projects:" key that takes ResourceFactory URLs.

Upgrade to Cayenne 4.0.M5

M5 is out. Let's upgrade. The new Cayenne has JCache integration. So we can remove a bunch of stuff from bootique-cayenne-jcache.

UPGRADE

Bootique InvalidationHandler was replaced by org.apache.cayenne.lifecycle.cache.InvalidationHandler that has a slightly different method signature (due to the need to keep Java 7 compatibility in Cayenne 4.0).

Support for contributing Cayenne modules

There's currently no way to add custom Cayenne DI modules to the stack. So either bridge Google DI or provide a contribute method. (or keep providing contribute methods for specific extensions)

Support for Cayenne 4.1

We need to support multiple major versions of Cayenne, making it a user choice. Specifically as of now this would be 4.0 (currently supported) and 4.1 (not yet supported). Need to design a way for the users to include either one or the other.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.