Note
Please note that the recipes in this document and the according code snippets are just examples. Depending on your Intershop Gradle Tools version the actual code may differ.
For detailed information about the version dependencies, please refer to Reference - CI Dependencies of Intershop Commerce Management.
This overview shows the necessary environment for developing and building with the Gradle Build Tools:
Setup of CI server and Code Quality Control server is not part of this document.
Phrase | Meaning |
---|---|
Version Control System (VCS) | Also known as source control, source code management systems (SCM), or revision control systems (RCS). VCS is a mechanism for keeping multiple versions of your files, so that when you modify a file you can still access the previous revisions. |
Artifact Repository | Place, where build and package software components are located. Provide a common interface to a dependency management system. |
Code Analysis | Process to analyze source code to calculate metrics, find bugs, etc. |
Continuous Delivery Pipeline | Sometimes called Deployment Pipeline, describes the stages, which code artifacts runs through source to production system. |
System Component | A software package of different code artifacts and files, that have to be deployed together. |
System Component Set | Is a container for system components, that needs to be build and branched together. |
Assembly | An assembly references one or more system components residing in the same or a configured artifact repository in order to deploy or deliver them together. |
Build Process | Compiles and packages files and code artifacts from a source project to deployable artifacts. |
Publish Process | The process which transfers the deployable artifacts to a configured artifact repository. |
Assembly Process | This process combines several system components to an assembly. |
Deployment Process | This process extracts files and code artifacts from an artifact repository and applies the configuration. |
Project Gradle Distribution | This is a customized Gradle distribution with the preconfigured artifact repositories and Gradle plugins. |
Gradle Plugin | A Gradle plugin packages up reusable pieces of build logic, which can be used across many different projects and builds. |
Project Gradle Plugin | This is a Gradle plugin which contains special corporate respectively project settings. |
Corporate Plugin | The term is used as a synonym for Project Gradle Plugin. |
Gradle Extension Object | Java Bean compliant class holding configurations for Gradle plugins. |
Gradle Wrapper | The Gradle Wrapper is the preferred way of starting a Gradle build. The wrapper is a batch script on Windows, and a shell script for other operating systems. When you start a Gradle build via the wrapper, Gradle will be automatically downloaded and used to run the build. See for more information The Gradle Wrapper in the Gradle documentation (2.11, 2.7, 2.3, 2.0, 1.8) |
Intershop Cluster | A number of hosts of different types serving an Intershop 7. |
Cluster Node | One separately deployable part of an Intershop cluster. A host can run multiple nodes of one Intershop cluster. |
Standardizing And Administering Your Enterprise Build Environment
If you want to start an Intershop project it is necessary to create a system component set. A component set contains Intershop cartridges and the configuration of a Gradle multi-project build. If you want to migrate from a previous version of Intershop it is necessary to consolidate your existing cartridges in system component sets. Please be aware that no dependency cycles between component sets are allowed.
The component set can be created using the scripts in the development-setup of an Intershop delivery package (see Cookbook - Setup CI Infrastructure (valid to GradleTools 1.1)).
How to adapt an existing system component set?
Adapt the settings.gradle file of the template.
To add a new cartridge, simply create it in a new sub directory – it is not necessary to change the settings.gradle file.
Replace the name 'project-name'
in the template below by the name of your component set.
// define root project name rootProject.name = 'project-name' def excludeList = ['gradle', '.gradle', 'target', 'build', 'bin', 'reports'] def dirMatch = {dirPath -> File dirFile = new File(dirPath) ! excludeList.contains(dirFile.name) && dirFile.list()?.contains('build.gradle') } rootDir.eachDirMatch(dirMatch) {File proj -> include ":${proj.name}" }
Change the build.gradle file in the project directory according to your requirements. This build configuration is used for all components of this component set.
description 'Components Storefront Applications' group = 'com.company.corporateshop' subprojects { apply plugin: 'intershop-base' group = 'com.company.corporateshop' intershop { productName = 'Corporate eCommerce Store' productCopyrightOwner = 'Corporate' } project.plugins.withType(JavaBasePlugin) { sourceCompatibility = 1.8 targetCompatibility = 1.8 } } buildscript { dependencies { classpath group: 'com.intershop.build.gradle', name: 'ish-component-plugin' classpath 'com.intershop.build.gradle:hot-code-reloading' } }
This configuration sets the productName
, productCopyrightOwner
(both parameters are used for the Java documentation), the compatibility of Java (is used for different compile tasks) and build script dependencies. Versions will be handled by the Intershop 'versioning' plugin. The 'versioning' plugin is injected by the project Gradle distribution. The 'assembly' plugin creates an Ivy file which is used by the 'versioning' plugin during the dependency resolution.
There is no configuration for the release process. An assembly is also not included. You find an extended example in the sources of the Responsive Starter Store.
Change version settings for your project in the gradle.properties. It is possible to overwrite this configuration with a gradle.properties file in the Gradle user home directory.
# project settings version = 1.0.0.0 # build plugin versions filter.com.intershop.build.set.cartridge-plugins = 1.0.0.0.+ filter.com.intershop.build.set.extension-plugins = 1.0.0.0.+
The Gradle wrapper is the preferred way to start a build with Gradle. This wrapper is very small and easy to use and should be part of the system component set.
It is also possible to explicitly include the sub projects. In this case the development team is responsible to maintain the settings.gradle file after a component is added or removed.
include('component_1') include('component_2')
For more information see the chapter The Build Lifecycle in the Gradle user guide.
If you add a component to a system component set it is necessary to configure the build of the component. The configuration depends on the sources of the component and build steps to perform.
How to configure a cartridge build?
Depending on the build steps to perform and the folder structure the build configurations of the components differ (see Project Layout in Concept - Gradle Build Tools).
Configuration that is common to all components/cartridges of the component set can be provided in the build.gradle file of the component set, see Recipe: Setup of a System Component Set. Configuration special to a single cartridge/component should be provided in the build.gradle file in the root directory of each component.
For a cartridge it is necessary to configure
by applying the corresponding plugins (see below) in the build.gradle file of each cartridge.
Note
If you apply a plugin for building Java code and no Java sources can be found, the build will fail. On the other hand if there are Java sources, but you do not apply the plugin for building Java code, they will neither be compiled nor packaged.
The same applies to static artifacts and the plugin for building them.
Each Intershop build plugin comes with a sensible default configuration. It is sufficient to configure only those values in which a cartridge build should deviate from the default.
For special build steps it is possible to use Gradle standard, 3rd-party plugins or to write your own ones. This cookbook recipe only covers the Intershop plugins. For more information on Gradle and standard Gradle plugins, please refer to http://www.gradle.org/documentation.
A component can be created inside the Intershop Studio. In future release we will provide Gradle plugins for the creation of system component sets and components. For now it is necessary to create the build.gradle file manually for a new component. After a migration from Ant it is necessary to verify the configuration. Not all Ant build configurations can be migrated automatically to the Gradle based build.
The following sections covers typical types of cartridges and their build.gradle files.
The cartridge contains Java sources, resource files or Java source files in the javasource folder. Cartridges with this characteristic must apply the build plugin java-cartridge. In most cases it is necessary to configure compile dependencies, because you use interfaces, classes etc. from other cartridges.
apply plugin: 'java-cartridge' intershop { displayName = 'Component - Calculation' description = 'This cartridge includes all special calculation functionality' } dependencies { compile project(':cid_bc_spreadsheet') compile group: 'com.intershop', name: 'core' compile group: 'com.intershop', name: 'businessobject' }
The dependency configuration in this example includes one dependency to another sub project of the system component set (':cid_bc_spreadsheet') and two external cartridge dependencies.
The cartridge contains Java sources and additional jar files from third-party vendors. Cartridges with this characteristic must apply the build plugin java-cartridge also, but the configuration must be extended.
apply plugin: 'java-cartridge' intershop { displayName = 'Component - Company Rule Engine' staticLibs = fileTree(dir: staticCartridgeLibFolder, include: '*.jar') } dependencies { compile project(':cid_bc_repository') compile group: 'com.intershop', name: 'core' compile group: 'com.intershop', name: 'tools' compile group: 'com.intershop', name: 'orm' }
The file collection staticLibs
is now configured for the extension intershop . The additional libraries of the cartridge are stored in the default cartridge folder (staticfiles/cartridge/lib) as declared by using the property staticCartridgeLibFolder
of the extension.
Dependency Management for Libraries
Since Gradle Tools 2.7 you can utilize Gradle's dependency management for handling 3rd party libraries, see Using Third-Party Libraries in a Cartridge.
The Intershop Gradle Tools 2.7 are the initial build, assembly and deployment tools of Intershop Commerce Suite 7.6.
The cartridge contains static content like pipelines, ISML templates etc., i.e., there are files in the folder staticfiles/cartridge/ which must be deployed. Please be aware that files in the folder staticfiles/cartridge/lib will be handled by the property staticLibs
as described above.
apply plugin: 'static-cartridge' intershop { displayName = 'Initialization of Company Backoffice' description = 'Initializes the SLDSystem site with the Operations organization during DBInit and DBMigrate.' } dependencies { compile project(':cid_as_system') compile group: 'com.intershop', name: 'core' compile group: 'com.intershop', name: 'bc_tendering' }
This is an example of an initialization cartridge. This cartridge does not contain ISML templates.
Note
If a cartridge contains ISML templates it is required to add the following dependencies:
dependencies { compile group: 'com.intershop', name: 'tools' compile group: 'com.intershop', name: 'isml' compile group: 'com.intershop', name: 'servletengine' compile group: 'com.intershop', name: 'core' }
This type of cartridge contains Java sources or resource files, third-party jar files and also static content. This is a combination of the previous cartridge types – so is the script.
apply plugin: 'java-cartridge' apply plugin: 'static-cartridge' intershop { displayName = 'Component - Calculation Extended' description = 'This cartridge includes all special calculation functionality' staticLibs = fileTree(dir: staticCartridgeLibFolder, include: '*.jar') } dependencies { compile project(':cid_bc_spreadsheet') compile group: 'com.intershop', name: 'core' compile group: 'com.intershop', name: 'businessobject' // cartridge contains also templates compile group: 'com.intershop', name: 'tools' compile group: 'com.intershop', name: 'isml' compile group: 'com.intershop', name: 'servletengine' compile group: 'com.intershop', name: 'core' }
Dependency Management for Libraries
Since Gradle Tools 2.7 you can utilize Gradle's dependency management for handling 3rd party libraries, see Using Third-Party Libraries in a Cartridge.
The Intershop Gradle Tools 2.7 are the initial build, assembly and deployment tools of Intershop Commerce Suite 7.6.
For some cartridges it is necessary to generate code with JAXB ( Java Architecture for XML Binding) or WSDL (Web Services Description Language) . The plugins for JAXB (jaxb) and for WSDL code generation ( wsdl ) are automatically applied by the intershop-javabase plugin, which itself is indirectly applied by the java-cartridge plugin.
The jaxb plugin comes with the extension jaxb and the wsdl plugin with the extension wsdl .
This is an example from an Intershop 7 cartridge:
apply plugin: 'java-cartridge' apply plugin: 'static-cartridge' intershop { displayName = 'Platform - WSRP Producer Implementation' } jaxb { configs { wsrp { xsd = 'staticfiles/definition/wsrp_v1_types.xsd' xjb = 'staticfiles/definition/wsrp.xjb' } } } wsdl { axis1Configs { wsrp_service { wsdlFile = 'staticfiles/wsdl/wsrp_service.wsdl' namespacePackageMappingFile = 'staticfiles/wsdl/NStoPkg.properties' wrapArrays = true noWrapping = true } } } dependencies { compile project(':tools') compile project(':core') }
The cartridge contains files in the folder staticfiles/general/root. These files should be deployed into IS_HOME (the local directory) of the Intershop installation.
apply plugin: 'static-cartridge' intershop { displayName = 'Extended initialization of Company Backoffice' description = 'Initializes the SLDSystem site with the Operations organization during DBInit and DBMigrate.' packages { local {} } } dependencies { compile project(':cid_as_system') compile group: 'com.intershop', name: 'core' compile group: 'com.intershop', name: 'bc_tendering' }
This example uses the default configuration for packaging an artifact of type 'local'. This configuration can be extended, see the Reference of the intershop extension.
How to use third-party libraries in my own Cartridge?
For Intershop 7 up to 7.5:
If the desired library is also used by the Intershop release, you can declare a cartridge dependency to com.intershop:tools
as described in Cartridge with Java Sources.
If you need to add additional libraries, you can either:
For Intershop 7.6 and later:
Starting with Intershop 7 version 7.6, 3rd party library dependencies are defined directly in the cartridge using them. Please refer to the Gradle User Guide for information about different configurations.
[...] dependencies { [...] // added to the compile classpath and to runtime compile group: 'com.google.guava', name: 'guava' // published as runtime dependencies, will be used for the server's runtime runtime group: 'org.slf4j', name: 'slf4j-api' // test* configurations are similar, but are only used for unit tests and never published testCompile group: 'org.hamcrest', name: 'hamcrest-all' }
Note
Adding new libraries
When adding new libraries, please ensure to redeploy your server in a development environment. This is necessary because the IS_SOURCE lookup does not cover transitive dependencies to third-party libraries.
The new approach introduced with Gradle Tools 2.7 only works for Intershop 7 versions starting with 7.6. Previous versions are not compatible.
This concept actually permeates the whole build & deploy lifecycle, so please refer to the according concepts for information about further stages of library handling. By default a developer only needs to add dependencies to the according cartridges, but the aggregation of libraries can be customized by existing mechanisms of the assembly process if needed.
How to create an infrastructure component, like a tool separate from the application server, to be deployed to IS_HOME?
Create the build.gradle file.
For this kind of component it is necessary to use the base plugin for components.
apply plugin: 'javabase-component' intershop { staticLibs = fileTree(dir: 'staticfiles/lib', include: '*.jar') staticLibsPublishExclude = '**/**' packages { local { srcDir fileTree(dir:'staticfiles/general', include: 'cid_tools/**') srcDir (jar.outputs.files, { into 'cid_tools/misc' rename { String fileName -> fileName = 'prjtool.jar' } }) } } }
Line 1 | Applies the javabase-component plugin. |
Line 3 | Start configuration for intershop extension. |
Line 4 | Configures folder with additional libraries. |
Line 6 | No additional libraries should be published separately. |
Line 8 | Start configuration of the package type 'local'. |
Line 9 | Static files are stored in 'staticfiles/general'. |
Line 10 | The created jar will be added to the package and renamed (see CopySpec). |
After existing components added to an component set it is necessary to migrate the build configuration from Ant to Gradle.
How to migrate the build configuration?
Intershop provides a migration plugin ish-migration
to ease this task.
Create a file migrate.gradle next to the existing build.gradle in the root directory of a system component set with the following content:
apply plugin: 'ish-migration' // Read property configuration def organizationMap = [:].withDefault {[]} def revisionMap = [:] if (project.hasProperty('componentsets')) { componentsets.split(';').each { String componentSet -> def components = project["${componentSet}.components"].split(';') def organization = project["${componentSet}.organization"] revisionMap["project.ext.${componentSet}_version"] = components organizationMap[organization].addAll(components) } } migration { organizations = organizationMap revisions = revisionMap defaultRevision = '${version}.+' // Uncomment the following line if you have to ignore cartridges // ignoredCartridges = ['cartridge1', 'cartridge2'] } buildscript { dependencies { classpath group: 'com.intershop.build.gradle', name: 'ish-component-plugin' classpath group: 'com.intershop.build.gradle', name: 'gradle-migration-plugin' } }
In the first part of the script special configuration attributes are read from project properties. The migration plugin adds the extension "migration". The extension has the following properties:
Type | Property | Description |
---|---|---|
Map | organizations | Assignment from components to an organization. |
Map | revisions | Assignment from components to revision expressions. |
String | defaultRevision | If there is no revision found in the map revisions , this expression is used. |
List<String> | ignoredCartridges | The listed cartridges will not be migrated. Specify their (unqualified) cartridge names, e.g., bc_foundation. |
Create or extend the properties file gradle.properties in the Gradle user home with the following properties:
... intershop.components = ac_order_export_xml;ac_order_status_import_xml;app_bo_catalog;app_bo_rest_job;bc_preview_test;dev_organizationinfo;sld_ch_base;\ sld_ch_consumer_orderimport_es64;sld_ch_consumer_plugin;sld_ch_partner_plugin;sld_enterprise_app;sld_preview;sld_preview_test;\ migration;monitor;sld_system_app;smc;app_sf_rest;app_sf_rest_b2c;app_sf_rest_smb;app_sf_webshop_b2c;app_sf_webshop_smb;ac_addresscheck_demo;\ dev_basketinfo;sld_ch_b2c_app;sld_ch_b2c_cm;sld_ch_b2c_image;sld_ch_sf_base;sld_pdf;ac_bmecat;bc_catalog;bc_catalog_orm;\ bc_catalog_test;bc_mvc;bc_product;bc_productbinding;bc_product_configuration;bc_product_orm;bc_product_test;bc_profanitycheck;bc_search;bc_xcs_test;\ ac_addresscheck_std;ac_ecircle;ac_giftcard_std;ac_oci;ac_payment_demo;ac_payment_std;ac_taxation_std;bc_addresscheck;bc_basket;bc_customer;bc_customer_orm;\ bc_giftcard;bc_giftpackaging;bc_marketing;bc_order;bc_orderprocess;bc_order_impex;bc_order_orm;bc_payment;bc_product_pricing;bc_product_rating;bc_product_rating_orm;\ bc_promotion;bc_rating;bc_rating_orm;bc_requisition;bc_shipping;bc_taxation;bc_tendering;bc_warranty;bc_wishlist;bc_wishlist_orm;bc_pmc;bc_pmc_auditing;\ bc_pmc_validation;bc_preview;bc_preview_orm;bc_pricing;bc_shipping_data;btc;bts;xcs;sld_ch_b2c_base;sld_ch_b2c_base_test;sld_mcm;sld_pmc;as_system;\ init_operations;init_smc;as_sales_organization;ucm_demo;ucm_demo_solr;ac_captcha_recaptcha;ac_captcha_simplecaptcha;ac_mail;ac_pdf_flyingsaucer;ac_ruleengine_drools;\ ac_ruleengine_drools_test;bc_address;bc_application;bc_application_test;bc_approval;bc_approval_test;bc_auditing;bc_auditing_orm;bc_auditing_test;bc_calculation;bc_captcha;\ bc_foundation;bc_foundation_test;bc_i18n;bc_i18n_test;bc_image;bc_mail;bc_organization;bc_pdf;bc_region;bc_repository;bc_ruleengine;bc_service;bc_spreadsheet;bc_user;\ bc_user_orm;bc_user_test;bc_validation;bc_validation_test;ui_web_library;app;businessobject;\cache;component;configuration;core;dbdelta;dev_lilith;emf;etest;\file;isml;jmx;\ messaging;orm;pf_cartridge;pf_core_test;pf_extension;pf_jmx_test;pf_objectgraph;pf_objectgraph_guice;pf_orm_test;pipeline;report;rest;servletengine;tools;tool_clc;\ tool_dbinit;wsrp;loaderapp;runtime;tcm;tloc;toolbox;tool_testrunner;tool_webtest;tool_webtest_htmlunit;tool_webtest_selenium;ac_giftcard_std_test;ac_taxation_std_test;\ bc_basket_test;bc_bts_test;bc_customer_test;bc_marketing_test;bc_mvc_test;bc_orderprocess_test;bc_pmc_test;bc_pricing_test;bc_product_pricing_test;bc_requisition_test;\ bc_service_test;bc_shipping_test;bc_wishlist_test;tests;test_resources;ucm_tests; intershop.organization = com.intershop componentsets = intershop ...
This is required to migrate dependencies from within <cartridge>.properties files, which do not contain a qualified name, i.e., the organization is missing. If you have dependencies to components with other organizations (like from other component sets of your company or Intershop services) add the following properties:
<first component set name>.components = <first cartridge>;<second cartridge> <first component set name>.organization = <organization of components in first component set> <second component set name>.components = <third cartridge>;<fourth cartridge> <second component set name>.organization = <organization of components in first component set> componentsets = intershop;<first component set name>;<second component set name>
There was a change in the location of SQL scripts for dbinit/dbmigrate. Move all files from
<cartridge>/javasource/resources/<cartridge>/dbinit|dbmigrate/scripts
to
<cartridge>staticfiles/cartridge/lib/resources/<cartridge>/dbinit|dbmigrate/scripts
The files in <cartridge>/javasource/<org>/<cartridge>/dbinit/data stay where they are.
Run the script.
cd <component set> gradlew -b migrate.gradle migrate
The migrate script cannot migrate all Ant build configurations. Please check your code generation configurations (JAXB, WSDL etc) and adjust them manually if necessary.
How to publish artifacts to a remote repository, like the artifact repository server used for the project?
This solution describes the publishing configuration if all build processes use the corporate plugin (see Cookbook - Setup CI Infrastructure (valid to GradleTools 1.1)).
By default all artifacts are published to the local repository. If you want to change that, it is necessary to create another directory for a special Gradle user home.
This folder must contain two files:
Disable the default configuration and set the version of your project in gradle.properties:
# disable default ish configuration systemProp.doNotUseInitDefaults=true ... # Version will be used for all components of your project # with the same GRADLE_USER_HOME version = 7.5.0.0 ... # filter for the own component set - latest release filter.<componentset org>.<componentset name> = <componentset version>.+ ... # these settings are used from the init script publishUsername=deploy publishPassword=intershop ...
It is necessary to declare your own filter and version settings.
Create your own Gradle initialization file with a special publishing configuration:
gradle.plugins.all { plugin -> // instanceof or plugins.withType won't work here, because of separate class loaders if (plugin.getClass().name != 'com.intershop.build.plugins.IntershopGradlePlugin') return gradle.corporateGradleRepos { useAllSharedRepos() } } allprojects { // calculate build number def now = new Date() ext { releaseBuildNo = now.format('yyyyMMddHHmmss') } beforeEvaluate { project -> // repo configuration for projects repositories { useAllSharedRepos() publishing { // set in gradle.properties setUsername(project.RepoUserLogin) setPassword(project.RepoUserPasswd) // The build number will be created by the corporate plugin // This plugins delivers also all information about the infrastructure. useComponentReleasePublishing(project.ext.releaseBuildNo) // this repository configuration can be used for snapshots // useSnapshotPublishing() } buildscript { // necessary for tloc and isml useComponentReleases() useBuildPluginsReleases() useMavenCentral() } } } }
Change the environment for the publishing process by setting the environment variable GRADLE_USER_HOME
to the directory you just created.
Run gradlew publish --refresh-dependencies
in the directory of the system component set to publish it to the remote repository.
gradlew publish --refresh-dependencies
in the directory of the assembly to publish it to the remote repository.These steps should be executed by a CI server process automatically. You should create separate build plans/projects:
It is also possible to add other configuration specific to the CI server build, e.g., Sonar code analysis and JavaDoc generation.
# sonar settings branchVersion = trunk sonarHostUrl = http://sonar.server.com/sonar sonarLogin = sonaruser sonarPassword = password sonarJDBCUrl = jdbc:postgresql://sonar.server.com:5432/sonar sonarJDBCDriverClass = org.postgresql.Driver sonarJDBCUserName = sonar sonarJDBCPassword = password # kind of modules, which should be analyzed (possible values are java, js, css) sonarModules = java,js # activate sonar for CI sonarCIBuildRun = true
It is not necessary to change the initialization script to activate sonar, as the SonarQubePlugin
is already applied by the plugin 'intershop-javabase'.
# release with javadoc releaseWithJavaDoc = true
... allprojects { ... project.tasks.withType(Javadoc) { task -> task.options { ... // all sub projects def kset = project.rootProject.getChildProjects().keySet() // available directories File apidoc = new File(project.ext.apidocpath) File[] files = apidoc.listFiles() } } ext.javadocLinks = [ "http://docs.oracle.com/javase/7/docs/api/", "http://docs.oracle.com/javaee/6/api/", "http://tomcat.apache.org/tomcat-7.0-doc/api/", "http://tomcat.apache.org/tomcat-7.0-doc/jspapi/", "http://tomcat.apache.org/tomcat-7.0-doc/servletapi/", "http://aopalliance.sourceforge.net/doc/", "http://asm.ow2.org/asm40/javadoc/user/", "http://ws.apache.org/axiom/apidocs/", ... ] as String[] afterEvaluate { project -> project.tasks.withType(Javadoc).each { Javadoc javadoc -> javadoc.options.links(project.ext.javadocLinks) } } ... }