Repository: cayenne
Updated Branches:
  refs/heads/master 8c3c49a4d -> c4b110043


CAY-2395 cdbimport: add option to create project file


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c4b11004
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c4b11004
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c4b11004

Branch: refs/heads/master
Commit: c4b110043e89e3ad74f28d74d272ab3c56e4ba16
Parents: 8c3c49a
Author: Nikita Timofeev <[email protected]>
Authored: Tue Jan 23 16:18:48 2018 +0300
Committer: Nikita Timofeev <[email protected]>
Committed: Tue Jan 23 16:18:48 2018 +0300

----------------------------------------------------------------------
 .../apache/cayenne/tools/DbImporterTask.java    |  17 ++
 .../cayenne/tools/DbImporterTaskTest.java       |   5 +
 .../apache/cayenne/tools/build-with-project.xml |  36 ++++
 .../reverse/configuration/ToolsModule.java      |   3 +
 .../reverse/dbimport/DbImportConfiguration.java |   9 +
 .../reverse/dbimport/DefaultDbImportAction.java |  65 ++++++-
 .../dbimport/DefaultDbImportActionTest.java     | 171 +++++++++++++++++--
 .../org/apache/cayenne/tools/DbImportTask.java  |  22 +++
 .../org/apache/cayenne/tools/DbImportIT.java    |  34 ++++
 .../cayenne/tools/dbimport_with_project.gradle  |  40 +++++
 .../apache/cayenne/tools/test_project_db.sql    |  53 ++++++
 docs/doc/src/main/resources/RELEASE-NOTES.txt   |   1 +
 .../apache/cayenne/tools/DbImporterMojo.java    |   9 +
 .../dialog/db/load/ModelerDbImportAction.java   |   6 +-
 14 files changed, 453 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
----------------------------------------------------------------------
diff --git 
a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java 
b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
index 5d22173..0d97213 100644
--- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
+++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java
@@ -224,6 +224,9 @@ public class DbImporterTask extends Task {
         config.setUsePrimitives(flag);
     }
 
+    /**
+     * @since 4.0
+     */
     public void setUseJava7Types(boolean flag) {
         config.setUseJava7Types(flag);
     }
@@ -248,6 +251,20 @@ public class DbImporterTask extends Task {
         config.setTargetDataMap(map);
     }
 
+    /**
+     * @since 4.1
+     */
+    public File getCayenneProject() {
+        return config.getCayenneProject();
+    }
+
+    /**
+     * @since 4.1
+     */
+    public void setCayenneProject(File cayenneProject) {
+        config.setCayenneProject(cayenneProject);
+    }
+
     public DbImportConfiguration toParameters() {
         return config;
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java 
b/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
index 71ae4e3..43745e7 100644
--- a/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
+++ b/cayenne-ant/src/test/java/org/apache/cayenne/tools/DbImporterTaskTest.java
@@ -95,6 +95,11 @@ public class DbImporterTaskTest {
     }
 
     @Test
+    public void testBuildWithProject() throws Exception {
+        
assertNotNull(getCdbImport("build-with-project.xml").getCayenneProject());
+    }
+
+    @Test
     public void testIncludeTable() throws Exception {
         test("build-include-table.xml");
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-with-project.xml
----------------------------------------------------------------------
diff --git 
a/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-with-project.xml
 
b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-with-project.xml
new file mode 100644
index 0000000..223de6a
--- /dev/null
+++ 
b/cayenne-ant/src/test/resources/org/apache/cayenne/tools/build-with-project.xml
@@ -0,0 +1,36 @@
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  ~   Licensed to the Apache Software Foundation (ASF) under one
+  ~  or more contributor license agreements.  See the NOTICE file
+  ~  distributed with this work for additional information
+  ~  regarding copyright ownership.  The ASF licenses this file
+  ~  to you under the Apache License, Version 2.0 (the
+  ~  "License"); you may not use this file except in compliance
+  ~  with the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~  Unless required by applicable law or agreed to in writing,
+  ~  software distributed under the License is distributed on an
+  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~  KIND, either express or implied.  See the License for the
+  ~  specific language governing permissions and limitations
+  ~  under the License.
+  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<project name="MyProject" default="dist" basedir=".">
+
+    <taskdef name="cdbimport" 
classname="org.apache.cayenne.tools.DbImporterTask" taskname="cdbimport"
+             classpath="${basedir}"/>
+
+    <target name="dist">
+        <cdbimport map="${context.dir}/WEB-INF/DefaultMap.map.xml"
+                   cayenneProject="${context.dir}/WEB-INF/cayenne-project.xml"
+                   adapter="org.apache.cayenne.dba.hsqldb.HSQLDBAdapter"
+                   driver="org.hsqldb.jdbcDriver"
+                   url="jdbc:hsqldb:hsql://localhost/bookmarker"
+                   username="sa">
+        </cdbimport>
+    </target>
+
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
----------------------------------------------------------------------
diff --git 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
index 8e3673d..1ab51f0 100644
--- 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
+++ 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/configuration/ToolsModule.java
@@ -24,6 +24,7 @@ import 
org.apache.cayenne.access.translator.batch.DefaultBatchTranslatorFactory;
 import org.apache.cayenne.access.types.DefaultValueObjectTypeRegistry;
 import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
 import org.apache.cayenne.configuration.Constants;
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DefaultRuntimeProperties;
 import org.apache.cayenne.configuration.RuntimeProperties;
@@ -34,6 +35,7 @@ import org.apache.cayenne.configuration.server.ServerModule;
 import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.configuration.xml.DefaultDataChannelMetaData;
 import org.apache.cayenne.configuration.xml.HandlerFactory;
+import org.apache.cayenne.configuration.xml.XMLDataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.xml.XMLDataMapLoader;
 import org.apache.cayenne.configuration.xml.XMLReaderProvider;
 import org.apache.cayenne.dba.db2.DB2Sniffer;
@@ -117,6 +119,7 @@ public class ToolsModule implements Module {
         binder.bind(DataSourceFactory.class).to(DriverDataSourceFactory.class);
 
         binder.bind(DataMapLoader.class).to(XMLDataMapLoader.class);
+        
binder.bind(DataChannelDescriptorLoader.class).to(XMLDataChannelDescriptorLoader.class);
         
binder.bind(HandlerFactory.class).to(ExtensionAwareHandlerFactory.class);
         
binder.bind(DataChannelMetaData.class).to(DefaultDataChannelMetaData.class);
         binder.bind(XMLReader.class).toProviderInstance(new 
XMLReaderProvider(true)).withoutScope();

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
----------------------------------------------------------------------
diff --git 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
index 110a7ff..06b04f0 100644
--- 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
+++ 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java
@@ -61,6 +61,7 @@ public class DbImportConfiguration {
     private String stripFromTableNames;
     private boolean forceDataMapCatalog;
     private boolean forceDataMapSchema;
+    private File cayenneProject;
 
     public DbImportConfiguration() {
         this.dataSourceInfo = new DataSourceInfo();
@@ -154,6 +155,14 @@ public class DbImportConfiguration {
         this.useJava7Types = useJava7Types;
     }
 
+    public File getCayenneProject() {
+        return cayenneProject;
+    }
+
+    public void setCayenneProject(File cayenneProject) {
+        this.cayenneProject = cayenneProject;
+    }
+
     public NameFilter createMeaningfulPKFilter() {
 
         if (meaningfulPkTables == null) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
----------------------------------------------------------------------
diff --git 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
index c31aaab..1e08844 100644
--- 
a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
+++ 
b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java
@@ -18,7 +18,11 @@
  ****************************************************************/
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
+import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNode;
 import org.apache.cayenne.configuration.ConfigurationTree;
+import org.apache.cayenne.configuration.DataChannelDescriptor;
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
@@ -55,8 +59,8 @@ import org.slf4j.Logger;
 
 import javax.sql.DataSource;
 import java.io.File;
-import java.io.FileNotFoundException;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.sql.Connection;
 import java.util.Collection;
 import java.util.Collections;
@@ -77,19 +81,22 @@ public class DefaultDbImportAction implements 
DbImportAction {
     private final DbAdapterFactory adapterFactory;
     private final DataMapLoader mapLoader;
     private final MergerTokenFactoryProvider mergerTokenFactoryProvider;
+    private final DataChannelDescriptorLoader dataChannelDescriptorLoader;
 
     public DefaultDbImportAction(@Inject Logger logger,
                                  @Inject ProjectSaver projectSaver,
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
                                  @Inject DataMapLoader mapLoader,
-                                 @Inject MergerTokenFactoryProvider 
mergerTokenFactoryProvider) {
+                                 @Inject MergerTokenFactoryProvider 
mergerTokenFactoryProvider,
+                                 @Inject DataChannelDescriptorLoader 
dataChannelDescriptorLoader) {
         this.logger = logger;
         this.projectSaver = projectSaver;
         this.dataSourceFactory = dataSourceFactory;
         this.adapterFactory = adapterFactory;
         this.mapLoader = mapLoader;
         this.mergerTokenFactoryProvider = mergerTokenFactoryProvider;
+        this.dataChannelDescriptorLoader = dataChannelDescriptorLoader;
     }
 
     protected static List<MergerToken> sort(List<MergerToken> reverse) {
@@ -172,7 +179,7 @@ public class DefaultDbImportAction implements 
DbImportAction {
         hasChanges |= syncProcedures(targetDataMap, sourceDataMap, 
loaderConfig.getFiltersConfig());
 
         if (hasChanges) {
-            saveLoaded(targetDataMap);
+            saveLoaded(targetDataMap, config);
         }
     }
 
@@ -383,10 +390,58 @@ public class DefaultDbImportAction implements 
DbImportAction {
         return hasChanges;
     }
 
-    protected void saveLoaded(DataMap dataMap) throws FileNotFoundException {
-        ConfigurationTree<DataMap> projectRoot = new 
ConfigurationTree<>(dataMap);
+    /**
+     * Save imported data.
+     * This can create DataMap and/or Project files.
+     */
+    protected void saveLoaded(DataMap dataMap, DbImportConfiguration config) 
throws MalformedURLException {
+        ConfigurationTree<ConfigurationNode> projectRoot;
+        if(config.getCayenneProject() == null) {
+            // Old version of cdbimport, no Cayenne project, need to save only 
DataMap
+            projectRoot = new ConfigurationTree<>(dataMap);
+        } else {
+            // Cayenne project is present
+            DataChannelDescriptor dataChannelDescriptor;
+            if(config.getCayenneProject().exists()) {
+                // Cayenne project file exists, need to read it and push 
DataMap inside
+                URLResource configurationResource = new 
URLResource(config.getCayenneProject().toURI().toURL());
+                ConfigurationTree<DataChannelDescriptor> configurationTree = 
dataChannelDescriptorLoader.load(configurationResource);
+                if(!configurationTree.getLoadFailures().isEmpty()) {
+                    throw new CayenneRuntimeException("Unable to load cayenne 
project %s, %s", config.getCayenneProject(),
+                            
configurationTree.getLoadFailures().iterator().next().getDescription());
+                }
+                dataChannelDescriptor = configurationTree.getRootNode();
+                // remove old copy of DataMap if it's there
+                DataMap oldDataMap = 
dataChannelDescriptor.getDataMap(dataMap.getName());
+                if(oldDataMap != null) {
+                    dataChannelDescriptor.getDataMaps().remove(oldDataMap);
+                }
+            } else {
+                // No project file yet, can simply create empty project with 
resulting DataMap
+                dataChannelDescriptor = new DataChannelDescriptor();
+                
dataChannelDescriptor.setName(getProjectNameFromFileName(config.getCayenneProject().getName()));
+                dataChannelDescriptor.setConfigurationSource(new 
URLResource(config.getCayenneProject().toURI().toURL()));
+                logger.info("Project file does not exist. New project will be 
saved into '" + config.getCayenneProject().getAbsolutePath());
+            }
+
+            dataChannelDescriptor.getDataMaps().add(dataMap);
+            projectRoot = new ConfigurationTree<>(dataChannelDescriptor);
+        }
+
         Project project = new Project(projectRoot);
         projectSaver.save(project);
+
+        logger.info("");
+        logger.info("All changes saved.");
+    }
+
+    protected String getProjectNameFromFileName(String fileName) {
+        int xmlExtPosition = fileName.lastIndexOf(".xml");
+        String name = fileName.substring(0, xmlExtPosition == -1 ? 
fileName.length() : xmlExtPosition);
+        if(fileName.startsWith("cayenne-")) {
+            name = name.substring("cayenne-".length());
+        }
+        return name;
     }
 
     protected DataMap load(DbImportConfiguration config, DbAdapter adapter, 
Connection connection) throws Exception {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
----------------------------------------------------------------------
diff --git 
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
 
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
index df8f8b1..364f770 100644
--- 
a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
+++ 
b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java
@@ -19,11 +19,11 @@
 package org.apache.cayenne.dbsync.reverse.dbimport;
 
 import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.DataNodeDescriptor;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
-import org.apache.cayenne.configuration.xml.DataChannelMetaData;
 import org.apache.cayenne.dba.DbAdapter;
 import org.apache.cayenne.dbsync.DbSyncModule;
 import org.apache.cayenne.dbsync.filter.NamePatternMatcher;
@@ -60,6 +60,8 @@ import org.junit.Test;
 import javax.sql.DataSource;
 import java.io.File;
 import java.net.URL;
+import java.nio.charset.Charset;
+import java.nio.file.Files;
 import java.sql.Connection;
 import java.sql.SQLException;
 import java.util.Collections;
@@ -132,7 +134,7 @@ public class DefaultDbImportActionTest {
         };
 
         final boolean[] haveWeTriedToSave = {false};
-        DefaultDbImportAction action = buildDbImportAction(new 
FileProjectSaver(Collections.<ProjectExtension>emptyList()) {
+        DefaultDbImportAction action = buildDbImportAction(new 
FileProjectSaver(Collections.emptyList()) {
             @Override
             public void save(Project project) {
                 haveWeTriedToSave[0] = true;
@@ -299,7 +301,9 @@ public class DefaultDbImportActionTest {
         MergerTokenFactoryProvider mergerTokenFactoryProvider = 
mock(MergerTokenFactoryProvider.class);
         when(mergerTokenFactoryProvider.get((DbAdapter)any())).thenReturn(new 
DefaultMergerTokenFactory());
 
-        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, 
adapterFactory, mapLoader, mergerTokenFactoryProvider) {
+        DataChannelDescriptorLoader dataChannelDescriptorLoader = 
mock(DataChannelDescriptorLoader.class);
+
+        return new DefaultDbImportAction(log, projectSaver, dataSourceFactory, 
adapterFactory, mapLoader, mergerTokenFactoryProvider, 
dataChannelDescriptorLoader) {
 
             protected DbLoader createDbLoader(DbAdapter adapter,
                                                Connection connection,
@@ -309,26 +313,32 @@ public class DefaultDbImportActionTest {
         };
     }
 
+    private URL getPackageURL() {
+        String packagePath = getClass().getPackage().getName().replace('.', 
'/');
+        URL packageUrl = getClass().getClassLoader().getResource(packagePath);
+        assertNotNull(packageUrl);
+        return packageUrl;
+    }
+
     @Test
-    public void testSaveLoaded() throws Exception {
+    public void testSaveLoadedNoProject() throws Exception {
         Logger log = mock(Logger.class);
         Injector i = DIBootstrap.createInjector(new DbSyncModule(), new 
ToolsModule(log), new DbImportModule());
+        DbImportConfiguration params = mock(DbImportConfiguration.class);
+        when(params.getCayenneProject()).thenReturn(null);
 
-        DefaultDbImportAction action = (DefaultDbImportAction) 
i.getInstance(DbImportAction.class);
+        URL outUrl = new URL(getPackageURL(), 
"dbimport/testSaveLoaded1.map.xml");
 
-        String packagePath = getClass().getPackage().getName().replace('.', 
'/');
-        URL packageUrl = getClass().getClassLoader().getResource(packagePath);
-        assertNotNull(packageUrl);
-        URL outUrl = new URL(packageUrl, "dbimport/testSaveLoaded1.map.xml");
+        DefaultDbImportAction action = (DefaultDbImportAction) 
i.getInstance(DbImportAction.class);
 
         File out = new File(outUrl.toURI());
         out.delete();
-        assertFalse(out.isFile());
+        assertFalse(out.exists());
 
         DataMap map = new DataMap("testSaveLoaded1");
         map.setConfigurationSource(new URLResource(outUrl));
 
-        action.saveLoaded(map);
+        action.saveLoaded(map, params);
 
         assertTrue(out.isFile());
 
@@ -337,6 +347,145 @@ public class DefaultDbImportActionTest {
     }
 
     @Test
+    public void testSaveLoadedWithEmptyProject() throws Exception {
+        Logger log = mock(Logger.class);
+        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new 
ToolsModule(log), new DbImportModule());
+        DbImportConfiguration params = mock(DbImportConfiguration.class);
+
+        URL projectURL = new URL(getPackageURL(), 
"dbimport/cayenne-testProject2.map.xml");
+        File projectFile = new File(projectURL.toURI());
+        projectFile.delete();
+        assertFalse(projectFile.exists());
+        when(params.getCayenneProject()).thenReturn(projectFile);
+
+        DefaultDbImportAction action = (DefaultDbImportAction) 
i.getInstance(DbImportAction.class);
+
+        URL dataMapURL = new URL(getPackageURL(), 
"dbimport/testSaveLoaded2.map.xml");
+
+        File dataMapFile = new File(dataMapURL.toURI());
+        dataMapFile.delete();
+        assertFalse(dataMapFile.exists());
+
+        DataMap map = new DataMap("testSaveLoaded2");
+        map.setConfigurationSource(new URLResource(dataMapURL));
+
+        action.saveLoaded(map, params);
+
+        assertTrue(dataMapFile.isFile());
+        assertTrue(projectFile.isFile());
+
+        String dataMapContents = Util.stringFromFile(dataMapFile);
+        assertTrue("Has no project version saved", 
dataMapContents.contains("project-version=\""));
+
+        String projectContents = Util.stringFromFile(projectFile);
+        assertTrue("Has no project version saved", 
projectContents.contains("project-version=\""));
+        assertTrue("Has no datamap in project", projectContents.contains("<map 
name=\"testSaveLoaded2\"/>"));
+    }
+
+    @Test
+    public void testSaveLoadedWithNonEmptyProject() throws Exception {
+        Logger log = mock(Logger.class);
+        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new 
ToolsModule(log), new DbImportModule());
+        DbImportConfiguration params = mock(DbImportConfiguration.class);
+
+        URL projectURL = new URL(getPackageURL(), 
"dbimport/cayenne-testProject3.map.xml");
+        File projectFile = new File(projectURL.toURI());
+        projectFile.delete();
+        assertFalse(projectFile.exists());
+
+        Files.write(projectFile.toPath(), ("<?xml version=\"1.0\" 
encoding=\"utf-8\"?>\n" +
+                "<domain 
xmlns=\"http://cayenne.apache.org/schema/10/domain\"\n"; +
+                "\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; 
+
+                "\t 
xsi:schemaLocation=\"http://cayenne.apache.org/schema/10/domain 
http://cayenne.apache.org/schema/10/domain.xsd\"\n"; +
+                "\t project-version=\"10\">\n" +
+                "</domain>").getBytes(Charset.forName("UTF-8")));
+        assertTrue(projectFile.isFile());
+
+        when(params.getCayenneProject()).thenReturn(projectFile);
+
+        DefaultDbImportAction action = (DefaultDbImportAction) 
i.getInstance(DbImportAction.class);
+
+        URL dataMapURL = new URL(getPackageURL(), 
"dbimport/testSaveLoaded3.map.xml");
+
+        File dataMapFile = new File(dataMapURL.toURI());
+        dataMapFile.delete();
+        assertFalse(dataMapFile.exists());
+
+        DataMap map = new DataMap("testSaveLoaded3");
+        map.setConfigurationSource(new URLResource(dataMapURL));
+
+        action.saveLoaded(map, params);
+
+        assertTrue(dataMapFile.isFile());
+        assertTrue(projectFile.isFile());
+
+        String dataMapContents = Util.stringFromFile(dataMapFile);
+        assertTrue("Has no project version saved", 
dataMapContents.contains("project-version=\""));
+
+        String projectContents = Util.stringFromFile(projectFile);
+        assertTrue("Has no project version saved", 
projectContents.contains("project-version=\""));
+        assertTrue("Has no datamap in project", projectContents.contains("<map 
name=\"testSaveLoaded3\"/>"));
+    }
+
+    @Test
+    public void testSaveLoadedWithNonEmptyProjectAndNonEmptyDataMap() throws 
Exception {
+        Logger log = mock(Logger.class);
+        Injector i = DIBootstrap.createInjector(new DbSyncModule(), new 
ToolsModule(log), new DbImportModule());
+        DbImportConfiguration params = mock(DbImportConfiguration.class);
+
+        URL projectURL = new URL(getPackageURL(), 
"dbimport/cayenne-testProject4.map.xml");
+        File projectFile = new File(projectURL.toURI());
+        projectFile.delete();
+        assertFalse(projectFile.exists());
+
+        Files.write(projectFile.toPath(), ("<?xml version=\"1.0\" 
encoding=\"utf-8\"?>\n" +
+                "<domain 
xmlns=\"http://cayenne.apache.org/schema/10/domain\"\n"; +
+                "\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; 
+
+                "\t 
xsi:schemaLocation=\"http://cayenne.apache.org/schema/10/domain 
http://cayenne.apache.org/schema/10/domain.xsd\"\n"; +
+                "\t project-version=\"10\">\n" +
+                "\t<map name=\"testSaveLoaded4\"/>\n" +
+                "</domain>").getBytes(Charset.forName("UTF-8")));
+        assertTrue(projectFile.isFile());
+
+        when(params.getCayenneProject()).thenReturn(projectFile);
+
+        DefaultDbImportAction action = (DefaultDbImportAction) 
i.getInstance(DbImportAction.class);
+
+        URL dataMapURL = new URL(getPackageURL(), 
"dbimport/testSaveLoaded4.map.xml");
+
+        File dataMapFile = new File(dataMapURL.toURI());
+        dataMapFile.delete();
+        assertFalse(dataMapFile.exists());
+
+        Files.write(dataMapFile.toPath(), ("<?xml version=\"1.0\" 
encoding=\"utf-8\"?>\n" +
+                "<data-map 
xmlns=\"http://cayenne.apache.org/schema/10/modelMap\"\n"; +
+                "\t xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"; 
+
+                "\t 
xsi:schemaLocation=\"http://cayenne.apache.org/schema/10/modelMap 
http://cayenne.apache.org/schema/10/modelMap.xsd\"\n"; +
+                "\t project-version=\"10\">\n" +
+                "\t<db-entity name=\"test\">\n" +
+                "\t\t<db-attribute name=\"test\" type=\"INT\"/>\n" +
+                "\t</db-entity>\n" +
+                "</data-map>").getBytes(Charset.forName("UTF-8")));
+        assertTrue(dataMapFile.isFile());
+
+        DataMap map = new DataMap("testSaveLoaded4");
+        map.setConfigurationSource(new URLResource(dataMapURL));
+
+        action.saveLoaded(map, params);
+
+        assertTrue(dataMapFile.isFile());
+        assertTrue(projectFile.isFile());
+
+        String dataMapContents = Util.stringFromFile(dataMapFile);
+        assertTrue("Has no project version saved", 
dataMapContents.contains("project-version=\""));
+        assertFalse(dataMapContents.contains("<db-entity"));
+
+        String projectContents = Util.stringFromFile(projectFile);
+        assertTrue("Has no project version saved", 
projectContents.contains("project-version=\""));
+        assertEquals("Has no or too many datamaps in project", 1, 
Util.countMatches(projectContents, "<map name=\"testSaveLoaded4\"/>"));
+    }
+
+    @Test
     public void testMergeTokensSorting() {
         LinkedList<MergerToken> tokens = new LinkedList<MergerToken>();
         tokens.add(new AddColumnToModel(null, null));

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
----------------------------------------------------------------------
diff --git 
a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
 
b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
index c640439..e5a9bd1 100644
--- 
a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
+++ 
b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java
@@ -62,6 +62,9 @@ public class DbImportTask extends BaseCayenneTask {
     @Internal
     private ReverseEngineering reverseEngineering;
 
+    @Internal
+    private File cayenneProject;
+
     public DbImportTask() {
         // this task should be executed every invocation, so it is never up to 
date.
         getOutputs().upToDateWhen(new Spec<Task>() {
@@ -127,6 +130,7 @@ public class DbImportTask extends BaseCayenneTask {
         config.setUsername(dataSource.getUsername());
         config.setUsePrimitives(reverseEngineering.isUsePrimitives());
         config.setUseJava7Types(reverseEngineering.isUseJava7Types());
+        config.setCayenneProject(cayenneProject);
 
         return config;
     }
@@ -167,4 +171,22 @@ public class DbImportTask extends BaseCayenneTask {
     public void adapter(String adapter) {
         setAdapter(adapter);
     }
+
+    @OutputFile
+    @Optional
+    public File getCayenneProject() {
+        return cayenneProject;
+    }
+
+    public void setCayenneProject(File cayenneProject) {
+        this.cayenneProject = cayenneProject;
+    }
+
+    public void cayenneProject(File cayenneProject) {
+        this.cayenneProject = cayenneProject;
+    }
+
+    public void cayenneProject(String cayenneProjectFileName) {
+        this.cayenneProject = getProject().file(cayenneProjectFileName);
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-gradle-plugin/src/test/java/org/apache/cayenne/tools/DbImportIT.java
----------------------------------------------------------------------
diff --git 
a/cayenne-gradle-plugin/src/test/java/org/apache/cayenne/tools/DbImportIT.java 
b/cayenne-gradle-plugin/src/test/java/org/apache/cayenne/tools/DbImportIT.java
index 00ecbe5..1fa16a7 100644
--- 
a/cayenne-gradle-plugin/src/test/java/org/apache/cayenne/tools/DbImportIT.java
+++ 
b/cayenne-gradle-plugin/src/test/java/org/apache/cayenne/tools/DbImportIT.java
@@ -114,9 +114,43 @@ public class DbImportIT extends BaseTaskIT {
         assertTrue(result.getOutput().contains("Table: SCHEMA_01.TEST2"));
     }
 
+    @Test
+    public void withProjectTaskSuccess() throws Exception {
+        String dbUrl = prepareDerbyDatabase("test_project_db");
+        File dataMap = new File(projectDir.getAbsolutePath() + 
"/datamap.map.xml");
+        assertFalse(dataMap.exists());
+        File project = new File(projectDir.getAbsolutePath() + 
"/cayenne-project.xml");
+        assertFalse(project.exists());
+
+        GradleRunner runner = createRunner("dbimport_with_project", 
"cdbimport", "--info", "-PdbUrl=" + dbUrl);
+
+        BuildResult result = runner.build();
+
+        assertNotNull(result.task(":cdbimport"));
+        assertEquals(TaskOutcome.SUCCESS, 
result.task(":cdbimport").getOutcome());
+
+        assertTrue(dataMap.isFile());
+        assertTrue(project.isFile());
+
+        // Check few lines from reverse engineering output
+        assertTrue(result.getOutput().contains("Table: APP.PAINTING"));
+        assertTrue(result.getOutput().contains("Db Relationship : toOne  
(EXHIBIT.GALLERY_ID, GALLERY.GALLERY_ID)"));
+        assertTrue(result.getOutput().contains("Db Relationship : toMany 
(GALLERY.GALLERY_ID, PAINTING.GALLERY_ID)"));
+        assertTrue(result.getOutput().contains("Create Table         ARTIST"));
+        assertFalse(result.getOutput().contains("Create Table         
PAINTING1"));
+        assertTrue(result.getOutput().contains("Skip relation: 
'.APP.ARTIST.ARTIST_ID <- .APP.PAINTING1.ARTIST_ID # 1'"));
+        assertTrue(result.getOutput().contains("Migration Complete 
Successfully."));
+    }
+
     private String prepareDerbyDatabase(String sqlFile) throws Exception {
         URL sqlUrl = 
Objects.requireNonNull(ResourceUtil.getResource(getClass(), sqlFile + ".sql"));
         String dbUrl = "jdbc:derby:" + projectDir.getAbsolutePath() + 
"/build/" + sqlFile;
+
+        // Try to open connection, it may fail at first time, so ignore it
+        try (Connection unused = DriverManager.getConnection(dbUrl + 
";create=true")) {
+        } catch (SQLException ignore) {
+        }
+
         try (Connection connection = DriverManager.getConnection(dbUrl + 
";create=true")) {
             try (Statement stmt = connection.createStatement()) {
                 for (String sql : SQLReader.statements(sqlUrl, ";")) {

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/dbimport_with_project.gradle
----------------------------------------------------------------------
diff --git 
a/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/dbimport_with_project.gradle
 
b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/dbimport_with_project.gradle
new file mode 100644
index 0000000..d99dd49
--- /dev/null
+++ 
b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/dbimport_with_project.gradle
@@ -0,0 +1,40 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+
+plugins {
+    id 'org.apache.cayenne'
+}
+
+cdbimport {
+    map 'datamap.map.xml'
+    cayenneProject 'cayenne-project.xml'
+
+    adapter 'org.apache.cayenne.dba.derby.DerbyAdapter'
+
+    dataSource {
+        username 'sa'
+        password ''
+        url dbUrl
+        driver 'org.apache.derby.jdbc.EmbeddedDriver'
+    }
+
+    dbImport {
+        excludeTable 'PAINTING1'
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_project_db.sql
----------------------------------------------------------------------
diff --git 
a/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_project_db.sql
 
b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_project_db.sql
new file mode 100644
index 0000000..82c8d79
--- /dev/null
+++ 
b/cayenne-gradle-plugin/src/test/resources/org/apache/cayenne/tools/test_project_db.sql
@@ -0,0 +1,53 @@
+--  Licensed to the Apache Software Foundation (ASF) under one
+--  or more contributor license agreements.  See the NOTICE file
+--  distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+--  to you under the Apache License, Version 2.0 (the
+--  "License"); you may not use this file except in compliance
+--  with the License.  You may obtain a copy of the License at
+--
+--    http://www.apache.org/licenses/LICENSE-2.0
+--
+--  Unless required by applicable law or agreed to in writing,
+--  software distributed under the License is distributed on an
+--  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+--  KIND, either express or implied.  See the License for the
+--  specific language governing permissions and limitations
+--  under the License.
+
+-- Test Schema for dbimport task test
+
+CREATE TABLE ARTIST (ARTIST_ID BIGINT  NOT NULL, ARTIST_NAME CHAR (254) NOT 
NULL, DATE_OF_BIRTH DATE , PRIMARY KEY (ARTIST_ID));
+CREATE TABLE NULL_TEST (ID INTEGER  NOT NULL GENERATED BY DEFAULT AS IDENTITY, 
NAME VARCHAR (100), PRIMARY KEY (ID));
+CREATE TABLE ARTIST_CT (ARTIST_ID INTEGER  NOT NULL, ARTIST_NAME CHAR (254) 
NOT NULL, DATE_OF_BIRTH DATE , PRIMARY KEY (ARTIST_ID));
+CREATE TABLE GENERATED_COLUMN (GENERATED_COLUMN INTEGER  NOT NULL GENERATED BY 
DEFAULT AS IDENTITY, NAME VARCHAR (250), PRIMARY KEY (GENERATED_COLUMN));
+CREATE TABLE GALLERY (GALLERY_ID INTEGER  NOT NULL, GALLERY_NAME VARCHAR (100) 
NOT NULL, PRIMARY KEY (GALLERY_ID));
+CREATE TABLE PAINTING1 (ARTIST_ID BIGINT , ESTIMATED_PRICE DECIMAL (10, 2), 
GALLERY_ID INTEGER , PAINTING_ID INTEGER  NOT NULL, PAINTING_TITLE VARCHAR 
(255) NOT NULL, PRIMARY KEY (PAINTING_ID));
+CREATE TABLE ARTGROUP (GROUP_ID INTEGER  NOT NULL, NAME VARCHAR (100) NOT 
NULL, PARENT_GROUP_ID INTEGER , PRIMARY KEY (GROUP_ID));
+CREATE TABLE EXHIBIT (CLOSING_DATE TIMESTAMP  NOT NULL, EXHIBIT_ID INTEGER  
NOT NULL, GALLERY_ID INTEGER  NOT NULL, OPENING_DATE TIMESTAMP  NOT NULL, 
PRIMARY KEY (EXHIBIT_ID));
+CREATE TABLE ARTIST_GROUP (ARTIST_ID BIGINT  NOT NULL, GROUP_ID INTEGER  NOT 
NULL, PRIMARY KEY (ARTIST_ID, GROUP_ID));
+CREATE TABLE PAINTING (ARTIST_ID BIGINT , ESTIMATED_PRICE DECIMAL (10, 2), 
GALLERY_ID INTEGER , PAINTING_DESCRIPTION VARCHAR (255), PAINTING_ID INTEGER  
NOT NULL, PAINTING_TITLE VARCHAR (255) NOT NULL, PRIMARY KEY (PAINTING_ID));
+CREATE TABLE ARTIST_EXHIBIT (ARTIST_ID BIGINT  NOT NULL, EXHIBIT_ID INTEGER  
NOT NULL, PRIMARY KEY (ARTIST_ID, EXHIBIT_ID));
+CREATE TABLE PAINTING_INFO (IMAGE_BLOB LONG VARCHAR FOR BIT DATA , PAINTING_ID 
INTEGER  NOT NULL, TEXT_REVIEW LONG VARCHAR , PRIMARY KEY (PAINTING_ID));
+
+ALTER TABLE PAINTING1 ADD FOREIGN KEY (ARTIST_ID) REFERENCES ARTIST 
(ARTIST_ID);
+ALTER TABLE ARTGROUP ADD FOREIGN KEY (PARENT_GROUP_ID) REFERENCES ARTGROUP 
(GROUP_ID);
+ALTER TABLE EXHIBIT ADD FOREIGN KEY (GALLERY_ID) REFERENCES GALLERY 
(GALLERY_ID);
+ALTER TABLE ARTIST_GROUP ADD FOREIGN KEY (ARTIST_ID) REFERENCES ARTIST 
(ARTIST_ID);
+ALTER TABLE ARTIST_GROUP ADD FOREIGN KEY (GROUP_ID) REFERENCES ARTGROUP 
(GROUP_ID);
+ALTER TABLE PAINTING ADD FOREIGN KEY (ARTIST_ID) REFERENCES ARTIST (ARTIST_ID);
+ALTER TABLE PAINTING ADD FOREIGN KEY (GALLERY_ID) REFERENCES GALLERY 
(GALLERY_ID);
+ALTER TABLE ARTIST_EXHIBIT ADD FOREIGN KEY (ARTIST_ID) REFERENCES ARTIST 
(ARTIST_ID);
+ALTER TABLE ARTIST_EXHIBIT ADD FOREIGN KEY (EXHIBIT_ID) REFERENCES EXHIBIT 
(EXHIBIT_ID);
+ALTER TABLE PAINTING_INFO ADD FOREIGN KEY (PAINTING_ID) REFERENCES PAINTING 
(PAINTING_ID);
+
+CREATE SEQUENCE PK_ARTGROUP AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_ARTIST AS BIGINT START WITH 200 INCREMENT BY 20 NO MAXVALUE 
NO CYCLE;
+CREATE SEQUENCE PK_ARTIST_CT AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_ARTIST_GROUP AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_EXHIBIT AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_GALLERY AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_GENERATED_COLUMN AS BIGINT START WITH 200 INCREMENT BY 20 
NO MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_NULL_TEST AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_PAINTING AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
+CREATE SEQUENCE PK_PAINTING1 AS BIGINT START WITH 200 INCREMENT BY 20 NO 
MAXVALUE NO CYCLE;
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/docs/doc/src/main/resources/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/docs/doc/src/main/resources/RELEASE-NOTES.txt 
b/docs/doc/src/main/resources/RELEASE-NOTES.txt
index 5fba36f..5b61a78 100644
--- a/docs/doc/src/main/resources/RELEASE-NOTES.txt
+++ b/docs/doc/src/main/resources/RELEASE-NOTES.txt
@@ -18,6 +18,7 @@ CAY-2377 Cleanup deprecated code.
 CAY-2391 cdbimport: add option to skip user-defined relationships
 CAY-2393 Add sqlserver-docker profile to automate tests on SQLServer
 CAY-2394 Upgrade to Apache Velocity 2.0
+CAY-2395 cdbimport: add option to create project file
 CAY-2396 Upgrade maven-assembly-plugin to 3.1.0
 
 Bug Fixes:

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
----------------------------------------------------------------------
diff --git 
a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
 
b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
index ab04c83..e6422c5 100644
--- 
a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
+++ 
b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java
@@ -71,6 +71,14 @@ public class DbImporterMojo extends AbstractMojo {
     private File map;
 
     /**
+     * Project XML file to use. If set cayenneProject will be created or 
updated after DB importing.
+     * This is optional parameter.
+     * @since 4.1
+     */
+    @Parameter
+    private File cayenneProject;
+
+    /**
      * An object that contains reverse engineering rules.
      */
     @Parameter(name = "dbimport", property = "dbimport", alias = "dbImport")
@@ -129,6 +137,7 @@ public class DbImporterMojo extends AbstractMojo {
         config.setStripFromTableNames(dbImportConfig.getStripFromTableNames());
         config.setTableTypes(dbImportConfig.getTableTypes());
         config.setTargetDataMap(map);
+        config.setCayenneProject(cayenneProject);
         config.setUrl(dataSource.getUrl());
         config.setUsername(dataSource.getUsername());
         config.setUsePrimitives(dbImportConfig.isUsePrimitives());

http://git-wip-us.apache.org/repos/asf/cayenne/blob/c4b11004/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
----------------------------------------------------------------------
diff --git 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
index 5e60bc4..b98313f 100644
--- 
a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
+++ 
b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/ModelerDbImportAction.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.cayenne.modeler.dialog.db.load;
 
+import org.apache.cayenne.configuration.DataChannelDescriptorLoader;
 import org.apache.cayenne.configuration.DataMapLoader;
 import org.apache.cayenne.configuration.server.DataSourceFactory;
 import org.apache.cayenne.configuration.server.DbAdapterFactory;
@@ -41,8 +42,9 @@ public class ModelerDbImportAction extends 
DefaultDbImportAction {
                                  @Inject DataSourceFactory dataSourceFactory,
                                  @Inject DbAdapterFactory adapterFactory,
                                  @Inject DataMapLoader mapLoader,
-                                 @Inject MergerTokenFactoryProvider 
mergerTokenFactoryProvider) {
-        super(logger, projectSaver, dataSourceFactory, adapterFactory, 
mapLoader, mergerTokenFactoryProvider);
+                                 @Inject MergerTokenFactoryProvider 
mergerTokenFactoryProvider,
+                                 @Inject DataChannelDescriptorLoader 
dataChannelDescriptorLoader) {
+        super(logger, projectSaver, dataSourceFactory, adapterFactory, 
mapLoader, mergerTokenFactoryProvider, dataChannelDescriptorLoader);
     }
 
     @Override

Reply via email to