Cayenne 4.2 new types demo
diff --git a/cayenne-jdbc-type-other/README.md b/cayenne-jdbc-type-other/README.md
new file mode 100644
index 0000000..0fd98b8
--- /dev/null
+++ b/cayenne-jdbc-type-other/README.md
@@ -0,0 +1 @@
+== Cayenne Example
\ No newline at end of file
diff --git a/cayenne-jdbc-type-other/pom.xml b/cayenne-jdbc-type-other/pom.xml
new file mode 100644
index 0000000..6a8d0db
--- /dev/null
+++ b/cayenne-jdbc-type-other/pom.xml
@@ -0,0 +1,122 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>cayenne-jdbc-type-other</artifactId>
+    <groupId>org.apache.cayenne.demo</groupId>
+    <version>1.0-SNAPSHOT</version>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <bootique.version>2.0.M1</bootique.version>
+        <cayenne.version>4.2.M2-SNAPSHOT</cayenne.version>
+
+        <postgres.jdbc.version>9.4.1209</postgres.jdbc.version>
+        <mysql.jdbc.version>8.0.21</mysql.jdbc.version>
+        <slf4j.version>1.7.30</slf4j.version>
+
+        <main.class>org.apache.cayenne.demo.Application</main.class>
+
+        <compiler.plugin.version>3.8.1</compiler.plugin.version>
+        <jar.plugin.version>3.2.0</jar.plugin.version>
+        <surefire.plugin.version>2.22.2</surefire.plugin.version>
+        <failsafe.plugin.version>2.22.2</failsafe.plugin.version>
+    </properties>
+
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <name>Apache Snapshot Repository</name>
+            <url>https://repository.apache.org/snapshots</url>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+        </repository>
+    </repositories>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>io.bootique.bom</groupId>
+                <artifactId>bootique-bom</artifactId>
+                <version>${bootique.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <!-- compile dependencies -->
+        <dependency>
+            <groupId>io.bootique</groupId>
+            <artifactId>bootique</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.bootique.cayenne</groupId>
+            <artifactId>bootique-cayenne42</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.bootique.jdbc</groupId>
+            <artifactId>bootique-jdbc-hikaricp</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.cayenne</groupId>
+            <artifactId>cayenne-server</artifactId>
+            <version>${cayenne.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${postgres.jdbc.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <version>${slf4j.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.jdbc.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.cayenne.plugins</groupId>
+                <artifactId>cayenne-modeler-maven-plugin</artifactId>
+                <version>${cayenne.version}</version>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>${jar.plugin.version}</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${compiler.plugin.version}</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire.plugin.version}</version>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>${failsafe.plugin.version}</version>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/Application.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/Application.java
new file mode 100644
index 0000000..318e840
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/Application.java
@@ -0,0 +1,36 @@
+package org.apache.cayenne.demo;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.bootique.BQCoreModule;
+import io.bootique.BQModuleProvider;
+import io.bootique.Bootique;
+import io.bootique.cayenne.v42.CayenneModule;
+import io.bootique.di.BQModule;
+import io.bootique.di.BaseBQModule;
+import org.apache.cayenne.configuration.server.ServerModule;
+import org.apache.cayenne.demo.model.types.JsonValueType;
+
+public class Application extends BaseBQModule implements BQModuleProvider {
+
+    public static void main(String[] args) {
+        Bootique.app(args)
+                .args("--config=classpath:config.yml", "-g")
+                .module(b -> BQCoreModule.extend(b)
+                        .addCommand(GeoTestCommand.class)
+                        .addCommand(JsonTestCommand.class)
+                )
+                .module(b -> CayenneModule.extend(b)
+                        .addModule(binder -> binder.bind(ObjectMapper.class).toProviderInstance(ObjectMapper::new))
+                        .addModule(binder -> ServerModule.contributeValueObjectTypes(binder).add(JsonValueType.class))
+                )
+                .autoLoadModules()
+                .exec()
+                .exit();
+    }
+
+    @Override
+    public BQModule module() {
+        return new Application();
+    }
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/GeoTestCommand.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/GeoTestCommand.java
new file mode 100644
index 0000000..af11120
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/GeoTestCommand.java
@@ -0,0 +1,43 @@
+package org.apache.cayenne.demo;
+
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import io.bootique.cli.Cli;
+import io.bootique.command.CommandOutcome;
+import io.bootique.command.CommandWithMetadata;
+import io.bootique.meta.application.CommandMetadata;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.demo.model.TestGeo;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.SQLExec;
+import org.apache.cayenne.value.Wkt;
+
+public class GeoTestCommand extends CommandWithMetadata {
+
+    @Inject
+    Provider<ServerRuntime> serverRuntimeProvider;
+
+    public GeoTestCommand() {
+        super(CommandMetadata.builder(GeoTestCommand.class).build());
+    }
+
+    @Override
+    public CommandOutcome run(Cli cli) {
+        ServerRuntime serverRuntime = serverRuntimeProvider.get();
+        ObjectContext context = serverRuntime.newContext();
+
+        SQLExec.query("DELETE FROM test_geo").execute(context);
+
+        TestGeo testGeo = context.newObject(TestGeo.class);
+        testGeo.setArea(new Wkt("POLYGON ((30 10, 40 40, 20 40, 40 50, 30 10))"));
+        context.commitChanges();
+
+        ObjectSelect.query(TestGeo.class).select(context)
+                .forEach(geo -> System.out.println(geo.getArea().getWkt()));
+
+        return CommandOutcome.succeeded();
+    }
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/JsonTestCommand.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/JsonTestCommand.java
new file mode 100644
index 0000000..3a009fc
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/JsonTestCommand.java
@@ -0,0 +1,74 @@
+package org.apache.cayenne.demo;
+
+import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Provider;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.bootique.cli.Cli;
+import io.bootique.command.CommandOutcome;
+import io.bootique.command.CommandWithMetadata;
+import io.bootique.meta.application.CommandMetadata;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.configuration.server.ServerRuntime;
+import org.apache.cayenne.demo.model.TestJson;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.SQLExec;
+
+class JsonTestCommand extends CommandWithMetadata {
+
+    @Inject
+    Provider<ServerRuntime> serverRuntimeProvider;
+
+    @Inject
+    ObjectMapper objectMapper;
+
+    public JsonTestCommand() {
+        super(CommandMetadata.builder(JsonTestCommand.class).build());
+    }
+
+    @Override
+    public CommandOutcome run(Cli cli) {
+
+        ServerRuntime serverRuntime = serverRuntimeProvider.get();
+        ObjectContext context = serverRuntime.newContext();
+        SQLExec.query("DELETE FROM test_json").execute(context);
+
+        createJsonObject(context);
+
+        listKeys(context);
+
+        getKey(context);
+
+        return CommandOutcome.succeeded();
+    }
+
+    private void createJsonObject(ObjectContext context) {
+        TestJson testJson = context.newObject(TestJson.class);
+        ObjectNode objectNode = new ObjectNode(objectMapper.getNodeFactory());
+        objectNode.put("test", 123);
+        objectNode.put("field1", "abc");
+        objectNode.put("field2", false);
+        testJson.setJson(objectNode);
+        context.commitChanges();
+    }
+
+    private void listKeys(ObjectContext context) {
+        List<String> keys = ObjectSelect.query(TestJson.class)
+                .column(TestJson.JSON.function("json_object_keys", String.class))
+                .select(context);
+
+        System.out.println("JSON keys: ");
+        keys.forEach(k -> System.out.println("\t" + k));
+    }
+
+    private void getKey(ObjectContext context) {
+        List<Integer> testValues = ObjectSelect.query(TestJson.class)
+                .column(TestJson.JSON.operator("->", Integer.class, "test"))
+                .select(context);
+
+        System.out.println("JSON values for path 'test':");
+        testValues.forEach(v -> System.out.println("\t" + v));
+    }
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestGeo.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestGeo.java
new file mode 100644
index 0000000..5015111
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestGeo.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.demo.model;
+
+import org.apache.cayenne.demo.model.auto._TestGeo;
+
+public class TestGeo extends _TestGeo {
+
+    private static final long serialVersionUID = 1L; 
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestJson.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestJson.java
new file mode 100644
index 0000000..d556efe
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/TestJson.java
@@ -0,0 +1,9 @@
+package org.apache.cayenne.demo.model;
+
+import org.apache.cayenne.demo.model.auto._TestJson;
+
+public class TestJson extends _TestJson {
+
+    private static final long serialVersionUID = 1L; 
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestGeo.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestGeo.java
new file mode 100644
index 0000000..a2b2b49
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestGeo.java
@@ -0,0 +1,111 @@
+package org.apache.cayenne.demo.model.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.time.LocalDateTime;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.value.Wkt;
+import org.apache.cayenne.exp.property.BaseProperty;
+import org.apache.cayenne.exp.property.DateProperty;
+import org.apache.cayenne.exp.property.NumericIdProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+
+/**
+ * Class _TestGeo was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _TestGeo extends BaseDataObject {
+
+    private static final long serialVersionUID = 1L; 
+
+    public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("id", "TestGeo", Integer.class);
+    public static final String ID_PK_COLUMN = "id";
+
+    public static final BaseProperty<Wkt> AREA = PropertyFactory.createBase("area", Wkt.class);
+    public static final DateProperty<LocalDateTime> DATE = PropertyFactory.createDate("date", LocalDateTime.class);
+
+    protected Wkt area;
+    protected LocalDateTime date;
+
+
+    public void setArea(Wkt area) {
+        beforePropertyWrite("area", this.area, area);
+        this.area = area;
+    }
+
+    public Wkt getArea() {
+        beforePropertyRead("area");
+        return this.area;
+    }
+
+    public void setDate(LocalDateTime date) {
+        beforePropertyWrite("date", this.date, date);
+        this.date = date;
+    }
+
+    public LocalDateTime getDate() {
+        beforePropertyRead("date");
+        return this.date;
+    }
+
+    @Override
+    public Object readPropertyDirectly(String propName) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch(propName) {
+            case "area":
+                return this.area;
+            case "date":
+                return this.date;
+            default:
+                return super.readPropertyDirectly(propName);
+        }
+    }
+
+    @Override
+    public void writePropertyDirectly(String propName, Object val) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch (propName) {
+            case "area":
+                this.area = (Wkt)val;
+                break;
+            case "date":
+                this.date = (LocalDateTime)val;
+                break;
+            default:
+                super.writePropertyDirectly(propName, val);
+        }
+    }
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        writeSerialized(out);
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        readSerialized(in);
+    }
+
+    @Override
+    protected void writeState(ObjectOutputStream out) throws IOException {
+        super.writeState(out);
+        out.writeObject(this.area);
+        out.writeObject(this.date);
+    }
+
+    @Override
+    protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        super.readState(in);
+        this.area = (Wkt)in.readObject();
+        this.date = (LocalDateTime)in.readObject();
+    }
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestJson.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestJson.java
new file mode 100644
index 0000000..e6838a3
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/auto/_TestJson.java
@@ -0,0 +1,111 @@
+package org.apache.cayenne.demo.model.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.BaseProperty;
+import org.apache.cayenne.exp.property.NumericIdProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.StringProperty;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Class _TestJson was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _TestJson extends BaseDataObject {
+
+    private static final long serialVersionUID = 1L; 
+
+    public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("id", "TestJson", Integer.class);
+    public static final String ID_PK_COLUMN = "id";
+
+    public static final BaseProperty<ObjectNode> JSON = PropertyFactory.createBase("json", ObjectNode.class);
+    public static final StringProperty<String> NAME = PropertyFactory.createString("name", String.class);
+
+    protected ObjectNode json;
+    protected String name;
+
+
+    public void setJson(ObjectNode json) {
+        beforePropertyWrite("json", this.json, json);
+        this.json = json;
+    }
+
+    public ObjectNode getJson() {
+        beforePropertyRead("json");
+        return this.json;
+    }
+
+    public void setName(String name) {
+        beforePropertyWrite("name", this.name, name);
+        this.name = name;
+    }
+
+    public String getName() {
+        beforePropertyRead("name");
+        return this.name;
+    }
+
+    @Override
+    public Object readPropertyDirectly(String propName) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch(propName) {
+            case "json":
+                return this.json;
+            case "name":
+                return this.name;
+            default:
+                return super.readPropertyDirectly(propName);
+        }
+    }
+
+    @Override
+    public void writePropertyDirectly(String propName, Object val) {
+        if(propName == null) {
+            throw new IllegalArgumentException();
+        }
+
+        switch (propName) {
+            case "json":
+                this.json = (ObjectNode)val;
+                break;
+            case "name":
+                this.name = (String)val;
+                break;
+            default:
+                super.writePropertyDirectly(propName, val);
+        }
+    }
+
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        writeSerialized(out);
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        readSerialized(in);
+    }
+
+    @Override
+    protected void writeState(ObjectOutputStream out) throws IOException {
+        super.writeState(out);
+        out.writeObject(this.json);
+        out.writeObject(this.name);
+    }
+
+    @Override
+    protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        super.readState(in);
+        this.json = (ObjectNode)in.readObject();
+        this.name = (String)in.readObject();
+    }
+
+}
diff --git a/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/types/JsonValueType.java b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/types/JsonValueType.java
new file mode 100644
index 0000000..2005783
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/java/org/apache/cayenne/demo/model/types/JsonValueType.java
@@ -0,0 +1,43 @@
+package org.apache.cayenne.demo.model.types;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.access.types.ValueObjectType;
+import org.apache.cayenne.value.Json;
+import org.apache.cayenne.di.Inject;
+
+public class JsonValueType implements ValueObjectType<ObjectNode, Json> {
+
+    @Inject
+    ObjectMapper objectMapper;
+
+    @Override
+    public Class<Json> getTargetType() {
+        return Json.class;
+    }
+
+    @Override
+    public Class<ObjectNode> getValueType() {
+        return ObjectNode.class;
+    }
+
+    @Override
+    public ObjectNode toJavaObject(Json value) {
+        try {
+            return (ObjectNode) objectMapper.readTree(value.getRawJson());
+        } catch (Exception e) {
+            throw new CayenneRuntimeException("Unable to parse JSON", e);
+        }
+    }
+
+    @Override
+    public Json fromJavaObject(ObjectNode object) {
+        return new Json(object.toString());
+    }
+
+    @Override
+    public String toCacheKey(ObjectNode object) {
+        return object.toString();
+    }
+}
diff --git a/cayenne-jdbc-type-other/src/main/resources/META-INF/services/io.bootique.BQModuleProvider b/cayenne-jdbc-type-other/src/main/resources/META-INF/services/io.bootique.BQModuleProvider
new file mode 100644
index 0000000..4a2d644
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/resources/META-INF/services/io.bootique.BQModuleProvider
@@ -0,0 +1 @@
+org.apache.cayenne.demo.Application
diff --git a/cayenne-jdbc-type-other/src/main/resources/cayenne-demo.xml b/cayenne-jdbc-type-other/src/main/resources/cayenne-demo.xml
new file mode 100644
index 0000000..723f184
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/resources/cayenne-demo.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<domain xmlns="http://cayenne.apache.org/schema/10/domain"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/domain https://cayenne.apache.org/schema/10/domain.xsd"
+	 project-version="10">
+	<map name="demo"/>
+</domain>
diff --git a/cayenne-jdbc-type-other/src/main/resources/config.yml b/cayenne-jdbc-type-other/src/main/resources/config.yml
new file mode 100644
index 0000000..0c0418f
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/resources/config.yml
@@ -0,0 +1,16 @@
+jdbc:
+  geo:
+    jdbcUrl: jdbc:postgresql://localhost:5432/cayenne-postgis
+    username: cayenne
+    password: cayenne
+  mysql:
+    jdbcUrl: jdbc:mysql://localhost:3306/cayenne-mysql?useUnicode=true&characterEncoding=UTF-8&generateSimpleParameterMetadata=true&allowPublicKeyRetrieval=true&useSSL=false
+    username: cayenne
+    password: cayenne
+
+cayenne:
+  datasource: geo
+  createSchema: false
+  maps:
+    - location: classpath:demo.map.xml
+      name: map1
\ No newline at end of file
diff --git a/cayenne-jdbc-type-other/src/main/resources/demo.map.xml b/cayenne-jdbc-type-other/src/main/resources/demo.map.xml
new file mode 100644
index 0000000..5143ec9
--- /dev/null
+++ b/cayenne-jdbc-type-other/src/main/resources/demo.map.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<data-map xmlns="http://cayenne.apache.org/schema/10/modelMap"
+	 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	 xsi:schemaLocation="http://cayenne.apache.org/schema/10/modelMap https://cayenne.apache.org/schema/10/modelMap.xsd"
+	 project-version="10">
+	<property name="defaultPackage" value="org.apache.cayenne.demo.model"/>
+	<property name="defaultSchema" value="public"/>
+	<db-entity name="test_geo">
+		<db-attribute name="area" type="OTHER" isMandatory="true" length="2147483647"/>
+		<db-attribute name="id" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true" length="10"/>
+	</db-entity>
+	<db-entity name="test_json">
+		<db-attribute name="id" type="INTEGER" isPrimaryKey="true" isGenerated="true" isMandatory="true" length="10"/>
+		<db-attribute name="json" type="OTHER" isMandatory="true" length="2147483647"/>
+		<db-attribute name="name" type="VARCHAR" length="255"/>
+	</db-entity>
+	<obj-entity name="TestGeo" className="org.apache.cayenne.demo.model.TestGeo" dbEntityName="test_geo">
+		<obj-attribute name="area" type="org.apache.cayenne.value.Wkt" db-attribute-path="area"/>
+	</obj-entity>
+	<obj-entity name="TestJson" className="org.apache.cayenne.demo.model.TestJson" dbEntityName="test_json">
+		<obj-attribute name="json" type="com.fasterxml.jackson.databind.node.ObjectNode" db-attribute-path="json"/>
+		<obj-attribute name="name" type="java.lang.String" db-attribute-path="name"/>
+	</obj-entity>
+	<dbImport xmlns="http://cayenne.apache.org/schema/10/dbimport">
+		<schema>
+			<includeTable>
+				<name>test_geo</name>
+			</includeTable>
+			<includeTable>
+				<name>test_json</name>
+			</includeTable>
+			<name>public</name>
+		</schema>
+		<tableTypes>
+			<tableType>TABLE</tableType>
+			<tableType>VIEW</tableType>
+		</tableTypes>
+		<forceDataMapCatalog>false</forceDataMapCatalog>
+		<forceDataMapSchema>false</forceDataMapSchema>
+		<namingStrategy>org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator</namingStrategy>
+		<skipPrimaryKeyLoading>false</skipPrimaryKeyLoading>
+		<skipRelationshipsLoading>false</skipRelationshipsLoading>
+		<useJava7Types>false</useJava7Types>
+		<usePrimitives>true</usePrimitives>
+	</dbImport>
+	<cgen xmlns="http://cayenne.apache.org/schema/10/cgen">
+		<destDir>..\java</destDir>
+		<mode>entity</mode>
+		<template>templates/v4_1/subclass.vm</template>
+		<superTemplate>templates/v4_1/superclass.vm</superTemplate>
+		<outputPattern>*.java</outputPattern>
+		<makePairs>true</makePairs>
+		<usePkgPath>true</usePkgPath>
+		<overwrite>false</overwrite>
+		<createPropertyNames>false</createPropertyNames>
+		<createPKProperties>true</createPKProperties>
+		<client>false</client>
+	</cgen>
+</data-map>