Related Documents
Document Properties
Kbid282B92
Last Modified03-Feb-2020
Added to KB08-Jun-2017
Public AccessEveryone
StatusOnline
Doc TypeGuidelines, Concepts & Cookbooks
Product
  • Gradle Tools
  • ICM 7.9

Cookbook - Deployment Tools ICM 7.9

1 Introduction

The present cookbook describes how to use the component-oriented deployment for Intershop Commerce Management 7.9 based on Gradle 2.11. While the recipes below may still contain sections referring to former Gradle Tools versions, please strictly stick to the 2.11 related content.

The present cookbook gives more in-depth knowledge to some selected deployment topics, including:

  • Preparation and configuration of the deployment of your own assembly in a production environment
  • Customizing and adding what gets deployed
  • Application of content filters

It is in the nature of Gradle that the lines between configuration and extension, administration and development blur. That is why this cookbook addresses administrators, DevOps engineers and developers and concerns development and deployment time.

The cookbook is mostly self-contained. Knowledge of the Concept - Gradle Deployment Tools is not required to follow the recipes, but helpful for a deeper understanding and straying off the predefined course.

1.1 Glossary


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 AnalysisProcess to analyze source code to calculate metrics, find bugs, etc.
Continuous Delivery PipelineSometimes called Deployment Pipeline, describes the stages, which code artifacts runs through source to production system.
System ComponentA software package of different code artifacts and files, that have to be deployed together.
System Component SetIs a container for system components, that needs to be build and branched together.
AssemblyAn 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 ProcessCompiles and packages files and code artifacts from a source project to deployable artifacts.
Publish ProcessThe process which transfers the deployable artifacts to a configured artifact repository.
Assembly ProcessThis process combines several system components to an assembly.
Deployment ProcessThis process extracts files and code artifacts from an artifact repository and applies the configuration.
Project Gradle DistributionThis is a customized Gradle distribution with the preconfigured artifact repositories and Gradle plugins.
Gradle PluginA Gradle plugin packages up reusable pieces of build logic, which can be used across many different projects and builds.
Project Gradle PluginThis is a Gradle plugin which contains special corporate respectively project settings.
Corporate PluginThe term is used as a synonym for Project Gradle Plugin.
Gradle Extension ObjectJava Bean compliant class holding configurations for Gradle plugins.
Gradle WrapperThe 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 ClusterA number of hosts of different types serving an Intershop 7.
Cluster NodeOne separately deployable part of an Intershop cluster. A host can run multiple nodes of one Intershop cluster.

1.2 References

2 Recipe: Prepare the Deployment

2.1 Problem

Before executing a deployment the host and its environment must be prepared.

2.2 Solution

Prerequisites for executing a deployment are:

  1. Meet the Software Requirements.
  2. Install a Gradle distribution or a Gradle wrapper.
  3. Make repositories that contain the assembly, all contained components and deployment plugins accessible to the host.
  4. Configure the location of the Gradle user home directory.
  5. Configure the deployment in a local deployment script settings.gradle (what to deploy in which version, host type, where to deploy, ports etc).

2.3 Discussion

2.3.1 Deployment for Developers

Developers can use a deployment that is triggered inside the assembly process and that requires only a simple properties file for configuration.

For more information, refer to the corresponding Gradle Developer Workflow cookbook:  

2.3.2 Gradle Distribution and Wrapper

You may use a standard Gradle distribution available from http://www.gradle.org, download it and extract it. 

Note

Before downloading, check which Gradle Tools version you are using to find the right version.

Intershop Gradle Tools always correspond to a certain Gradle / ICM version. For more information on version dependencies, see Reference - CI Dependencies of Intershop Commerce Management.


You may also use a project Gradle distribution, as created through the corresponding Setup CI Infrastructure cookbook in your artifact repository. This has the advantage that the repositories are preconfigured automatically.

You may either download the Gradle distribution manually or use a Gradle wrapper - a small Java program that will download Gradle, extract it and run it automatically. It is recommended to store and retrieve the Gradle wrapper from a VCS.

See also the corresponding Gradle user guide on the Gradle Wrapper:

The corresponding Setup CI Infrastructure cookbook helps you to create a wrapper:

2.3.3 Make Repositories Accessible

The deployment copies files to deploy from an artifact repository. The repository is filled by a build process/copying pre-built components from other repositories. Two main types of repositories are

  • File system based repository, e.g., a local or mounted folder,
  • An URL based repository like a file server or dedicated artifact repository (like e.g., Sonatype Nexus, Artifactory)

Making them accessible may thus mean to mount an NFS or a DVD or opening firewalls. To tell Gradle where the repositories can be found refer to the Recipe: Configure the Deployment.

2.3.4 Configure Location of Gradle User Home

Gradle stores caches and configurations in a folder called Gradle user home. When using a remote repository (i.e., URL, not file system based), this can become quite large. The default location at <OS user home>/.gradle may not be the best place in this case. Reconfigure the location by setting the environment variable GRADLE_USER_HOME.

2.3.5 Configure the Deployment

Gradle itself is a general purpose automation tool. The central file telling Gradle what to automate is the Gradle settings file, typically called settings.gradle.

For the deployment it contains:

  • Logic telling Gradle to execute an Intershop deployment, by including the deployment-bootstrap plugin.
  • Which assembly to deploy
  • Where to deploy it
  • How to configure host names, ports, permissions etc.
  • Custom deployment logic
  • Inclusion of other deployment scripts/configuration files

See Recipe: Configure the Deployment for details about the contents of this file.

Also see the Concept - Gradle Deployment Tools and the corresponding Gradle user guide on Multi-project Builds (2.11, 2.7, 2.3, 2.1, 1.8).

The settings file can be stored anywhere in the local file system, except any folder which is processed by the deployment. We recommend to put it into the parent folder of your deployment (if you deploy into a single directory). If the local deployment script is called settings.gradle and located in the current working directory or any parent directory Gradle will automatically find it. If you differ from naming or location, you have to pass in the Gradle command line option -c, --settings-file , upon every execution, see the corresponding Gradle user guide on command line usage (2.11, 2.7, 2.3, 2.1, 1.8).

We recommend to store the settings.gradle in a VCS or use a configuration management tool to generate/distribute it.

2.3.6 Executing Gradle

To execute the deployment run the Gradle command (gradlew for invocation through the wrapper or gradle for direct invocation) in the directory of the settings file and pass a Gradle task to execute. Available tasks can be displayed by:

<gradle command> tasks

2.3.7 Prerequisites of the Deployed Application

When deploying an Intershop 7 based solution additional system prerequisites must be met - like an installed Oracle client and a prepared database.

3 Recipe: Configure the Deployment

Note

This recipe is only valid for the additional Solr Cloud assembly for Intershop 7.9. If this assembly is not used, the original recipe Recipe: Configure the Deployment (valid to 7.8) remains valid.

3.1 Problem

Before executing a deployment must be configured in the settings.gradle file.

3.2 Solution

To configure your deployment create a settings.gradle file, containing the following information:

  • Repositories
  • Which assembly to deploy in which version
  • Which host type and environment to select
  • Java directory
  • Share and local directories
  • Appserver instances
  • Database account
  • License file
  • Appserver instance ID
  • Platform ID
  • Ports for Web Adapter
  • Ports and network interface for application server (Nodemanager)
  • User name and group

The general structure of a settings.gradle for deployment is:

buildscript {
    gradle.injectRepositories(repositories, configurations)
    dependencies {
        classpath 'com.intershop.build.gradle:deployment-launcher:<version>'
    }
}
 
apply plugin: com.intershop.deploy.bootstrap.DeploymentBootstrapPlugin
 
deploymentBootstrap {
    gradle.injectRepositories(repositoryHandler, configurationContainer)
 
    // assembly block
	assembly ('<assembly organization>:<assembly name>:<assembly version>') {
	    hostType {
    	    environment '<environment>'
    	    hostType '<host type>'
	    }
	}
 
    // config block
	config {
	    <config DSL block>
	}
}

3.3 Discussion

3.3.1 Repository Configuration

The deployment requires repositories to resolve the assembly, all components to deploy and the deployment plugins from. The settings.gradle template above assumes, that

  • The repository configuration is provided as an extension property injectRepositories on the global gradle object, see Gradle DSL Reference 2.112.72.32.0.
  • This property is set to a closure that takes a RepositoryHandler, see Gradle DSL Reference (2.11, 2.72.32.0), and a ConfigurationContainer, see Gradle DSL Reference ( 2.11, 2.72.32.0)
  • The closure adds repositories to the passed in RepositoryHandler and may optionally control details of the dependency resolution process on the ConfigurationContainer object

This closure is best provided in a Gradle init script. The Project Gradle Plugin created with the corresponding Setup CI Infrastructure cookbook already provides this closure. Using a Project Gradle Distribution (directly or through a Gradle wrapper) will therefore automatically declare the repositories.

You may also declare them manually in a Gradle init script as shown in the following example:

gradle.ext.injectRepositories = { RepositoryHandler repositories, ConfigurationContainer configurations -> 
    repositories.with {
        // Declare repositories using Gradle's repository DSL
        maven {
            url "http://repo.mycompany.com/maven2"
        }

        ivy {
            url "http://repo.mycompany.com/repo"
            layout "pattern", {
                artifact "[module]/[revision]/[type]/[artifact].[ext]"
            }
        }
    }
}

See Gradle user guide on Dependency Management (2.11, 2.72.32.0) or Gradle DSL documentation on RepositoryHandler (2.112.72.32.0) for details on how to declare repositories.

3.3.2 Assembly hostType DSL Block

The deployment must know which assembly to deploy. Also it must determine - very early in deployment - which components to create as projects (see Concept - Gradle Deployment Tools), based on host type and environment to deploy. See Concept - Continuous Delivery Tools (in the sections Assembly Subsset Host Type and Assembly Subset Environment) and Concept - Gradle Assembly Tools for a general definition of what a host type and an environment is and which ones are available by default.

 Options (defined by assembly)
hostType

all, webserver,appserver,share, discoveryserver, microservices

environmentdevelopment, test, production

3.3.3 Config DSL Block

The config block configures the root level Gradle project during deployment, which represents the assembly. It contains most significant deployment configurations. It is segmented into sub-blocks.

The following tables gives an overview about sub-blocks of the config block and their properties. The last three columns show for which host-types they are required.

ConfigurationStructure | ExampleDescriptionappserversharewebserver

Java directory

Structure:

target.javaHome = File

Example:

target {
       javaHome =  new File( '/path/to/jdk' )
       // must reference to a jdk directore (see below)
}

/*
[/ or C:\]
|-- path
     |-- to
         |-- jdk
             |-- bin
             |   |-- .java (linux)
             |   |-- .java.exe (windows)
             |-- jre
                     |-- bin
                             |-- .java (linux)
                             |-- .java.exe (windows)

*/

Specify the JDK which should be used in scripts, e.g. to execute the server-startup.

(DEFAULT) By default this Value is set to the Java which executes the Gradle-Process.

JDK lookup mechanism:

Gradle tries to find a JDK installation, if the Gradle-Process is executed via a JRE based in a JDK's directory. E.g.:

  • Gradle-Process Java is /path/to/jdk/jre/bin/java
  • The lookup sets the Java-Path for the deployment to /path/to/jdk
  • If the parent directory is not identified as JDK directory, the Deployment fails.

The mechanism doesn't work, if target.javaHome is configured. In this case target.javaHome must point to a valid JDK directory with jre directory inside.

(tick)(tick)(tick)
Share directory

Structure:

target.shareDirectory = File

Example:

target {
shareDirectory = new File(settingsDir, 'share')

}

Specify the share directory to deploy to (IS_SHARE).

(warning) IS_SHARE may not be the same directory as your settingsDir

(tick)(tick)(tick)
Local directory

Structure:

target.localDirectory = File

Example:

target {
localDirectory = new File(settingsDir, 'local')
}

Specify the local directory (IS_HOME)

(warning) IS_HOME may not be the same directory as your settingsDir

(tick) (tick)
Application server settings

Structure:

appserver {
hostname = 'Host'
nodemanagerNetworkInterface = 'Address'
nodemanagerJmxPort = Port
}

Example:

appserver {
hostname = 'myhost.domain.invalid'
nodemanagerJmxPort = 10055
}
Configuration relevant for all appservers of the installation. The nodemanagerNetworkInterface defaults to 127.0.0.1. The hostname defaults to localhost for single-machine installations.(tick)  
Appserver instances

Structure:

appserver {
instances {
appserver[n] {
tomcatShutdownPort = Port1
tomcatHttpPort = Port2
tomcatHttpsPort = Port3
appserverPort = Port4
serverGroups = ['GROUP1', 'GROUP2']
}
}
}

Example:

appserver {
instances {
appserver0 {
tomcatShutdownPort = 10050
tomcatHttpPort = 10051
tomcatHttpsPort = 10052
appserverPort = 10053
}
        appserver1 {
tomcatShutdownPort = 10060
tomcatHttpPort = 10061
tomcatHttpsPort = 10062
appserverPort = 10063
serverGroups = ['BOS']
}
}
}

Specify the appserver instances. For each instance add a block for the application server. The ports must be unique and unused on the target system. Even, if not required, stay with the naming schema 'appserver0', 'appserver1', etc. Server groups are optional and default to ['WFS', ' BOS', ' JOB'].

Appserver-specific configuration is stored in IS_HOME/config per default, but can be configured via appserver.configPath.

(tick)  

Database account

(Gradle Tools ≤ 1.1)

Structure:

database {
host = '<FILL IN>'
port = <FILL IN>
sid = '<FILL IN>'
tnsAlias = '<FILL IN>'
user = '<FILL IN>'
password = '<FILL IN>'
oracleClientDir = new File('<FILL IN>')
}

Example:

database {
host = 'localhost'
port = 1521
sid = 'ISORCL1'
tnsAlias = 'ISSERVER.world'
user = 'dbuser'
password = 'dbpassword'
oracleClientDir = new File('C:/path/to/oracle/client/dir')
}
Specificy the database settings. (tick) 

Database account

(Gradle Tools ≥ 2.0)

Structure:

database {
host = '<FILL IN>'
port = <FILL IN>
serviceName = '<FILL IN>'
tnsAlias = '<FILL IN>'
user = '<FILL IN>'
password = '<FILL IN>'
oracleClientDir = new File('<FILL IN>')
}

Example:

database {
host = 'localhost'
port = 1521
serviceName = 'ISORCL1.world'
tnsAlias = 'ISSERVER.world'
user = 'dbuser'
password = 'dbpassword'
oracleClientDir = new File('C:/path/to/oracle/client/dir')
}

Specificy the database settings.

SID-based configuration is deprecated, prefer to use service name to designate the database instance.

 (tick) 
License file

Structure:

license.licenseFile = File

Example:

license {
licenseFile = new File('C:/path/to/license.xml')
}
Specify the path to your license file. The file must be available at your target system. (tick)  
Instance ID

Structure:

target.instanceId = '<FILL IN>'

Example:

target.instanceId = '9'
Specify the ID of your instance. The ID must be unique on your target system.(tick)(tick)  (tick)
Platform ID

Structure:

target.platform = '<FILL IN>'

Example:

target {
platform = 'linux.rhel.x86_64'
}

Specify the ID of your platform. Supported values are:

  • linux.rhel.x86_64
  • linux.sles.x86_64
  • win.x86_64
(tick) (tick)
Web Adapter settings

Structure:

webadapter {
hostname = '<FILL IN>'
port = PORT1
securePort = PORT2
 sharedMemoryKey = '<FILL IN>'
configurationServices = ['SVC1', 'SVC2']
    serverGroups = ['WFS', 'BOS', 'JOB']
}

Example:

webadapter {
hostname = 'localhost'
port = 80
securePort = 443
sharedMemoryKey = '0x2001'
configurationServices = ['localhost:10053']
}

Specify the settings for running the Web Adapter.

configurationServices is a list of hosts (format: hostname:port), whose configuration servlets will be used by the Web Adapter. For single-machine deployments (Host type: all) this value is optional and defaults to 'localhost:$appserverPort' for each locally configured appserver instance.

serverGroups (since Gradle Tools ≥ 2.0) configures all the server groups known to the Web Adapter. For single-machine deployments (Host type: all) this value defaults to the union of all appservers' server groups, for other host types it defaults to ['WFS', 'BOS', 'JOB'].

  (tick)

Web Adapter settings

(for share only)

Structure:

webadapter {
hostname = '<FILL IN>'
port = PORT1
securePort = PORT2
serverGroups = ['WFS', 'BOS', 'JOB']
}

Example:

webadapter {
hostname = 'customer.de'
port = 80
securePort = 443
    serverGroups = ['WFS', 'BOS', 'JOB', 'STG']
}

Specify the settings how to generate public URLs directed at a Web Adapter (or load balancer).

serverGroups exists since Gradle Tools ≥ 2.0.

 (tick) 

External SSL box configuration

(Gradle Tools 2.0)

Structure:

webadapter {
useSSLBox = true|false
sslBoxSecuredPort = PORT3
}

Example:

webadapter {
useSSLBox = true
sslBoxSecuredPort = 8443
}
Specifies whether or not an external SSL box is being used, and which port the Web Adapter should listen to for secured connections .useSSLBox defaults to false.   

Multicast settings

(until Gradle Tools 1.0)

Structure:

multicast {
appserverMulticastAddress = '<FILL IN>'
appserverMulticastPort = PORT1
appserverMulticastInterface = '<FILL IN>'
tcmMulticastAddress = '<FILL IN>'
tcmMulticastPort = PORT2
tcmMulticastInterface = '<FILL IN>'
cacheMulticastAddress = '<FILL IN>'
cacheMulticastPort = PORT3
cacheMulticastInterface = '<FILL IN>'
}

Example:

multicast {
appserverMulticastAddress = '239.192.12.34'
    appserverMulticastPort      = 50000
    appserverMulticastInterface = '127.0.0.1'
tcmMulticastAddress = '239.192.12.34'
tcmMulticastPort = 50001
    tcmMulticastInterface       = '127.0.0.1'
cacheMulticastAddress = '239.192.12.34'
cacheMulticastPort = 50002
    cacheMulticastInterface   = '127.0.0.1'
}
Specify the multicast addresses, ports and (optionally) interfaces to bind to. (tick) 

Multicast settings

(Gradle Tools ≥ 1.1, for share only)

Structure:

multicast {
appserver {
     address = '<IP adress>'
     port = <port>
}
tcm {
     address = '<IP address>'
     port = <port>
}
cache {
     address = '<IP address>'
     port = <port>
}
orm {
address = '<IP address>'
port = <port>
}
}

Example:

multicast {
appserver {
     address = '239.192.12.34'
     port = 50000
}
tcm {
     address = '239.192.12.34'
     port = 50001
}
    cache {
     address = '239.192.12.34'
     port = 50002
}
orm {
address = '239.192.12.34'
port = 50003
}
}

Specify the multicast addresses and ports. This part of the multicast configuration applies cluster-wide.

 

 
(tick)
 

Multicast settings

(Gradle Tools ≥ 1.1, for appserver only)

Structure:

multicast {
all {
     networkInterface = '<IP adress>'
}
}

Example:

multicast {
all {
     networkInterface = '192.168.0.1'
}
}
Specify the network interface to bind multicast connections to. This part of the multicast configuration applies to the deployed appserver only.(tick)  

AWS (Amazon Web Service) messaging settings

(Gradle Tools ≥ 2.1)

Structure:

aws {
appserver {
     topicName = '<topic name>'
     region = '<region>'
credentialsProvider = '<credentials provider, optional>'
receiveMessageWaitTime = <wait time (seconds), optional>
sendAsync = <send asynchronously, optional>
}
    tcm {
topicName = '<topic name>'
     region = '<region>'
credentialsProvider = '<credentials provider, optional>'
receiveMessageWaitTime = <wait time (seconds), optional>
sendAsync = <send asynchronously, optional> 
}
    cache { 
topicName = '<topic name>'
     region = '<region>'
credentialsProvider = '<credentials provider, optional>'
receiveMessageWaitTime = <wait time (seconds), optional>
sendAsync = <send asynchronously, optional> 
}
    orm {
topicName = '<topic name>'
     region = '<region>'
credentialsProvider = '<credentials provider, optional>'
receiveMessageWaitTime = <wait time (seconds), optional>
sendAsync = <send asynchronously, optional>
}
    all {
topicName = '<topic name>'
     region = '<region>'
credentialsProvider = '<credentials provider, optional>'
receiveMessageWaitTime = <wait time (seconds), optional>
sendAsync = <send asynchronously, optional>
}
}

Example:

aws {    
    all {
region = 'eu-west-1'
}

appserver {
     topicName = 'appserver-event'
}
    tcm {
topicName = 'tcm-event'
}
    cache { 
topicName = 'cache-event'
}
    orm {
topicName = 'orm-event'
}
}
Specify cluster-wide AWS messaging settings for each messenger channel. The all block can be used to specify common messenger settings. (tick) 

User settings

Structure:

assemblyDeployment.user      = '<FILL IN>'
assemblyDeployment.userGroup = '<FILL IN>'

Example:

assemblyDeployment {
user = 'iwas1'
userGroup = 'iwas1'
}

Specify the user to run the deployed application with. The user will not be created during setup. Your need to create it before the deployment starts. You have to execute the deployment with this user.

(tick) (tick)

Solr search service


Structure:

solr6 {
zooKeeperHostList = '<HOST_1>;<HOST_2>;<HOST_N>'
    clusterIndexPrefix = '<MYHOST-INSANCE>' 
}

Example:

solr6 {
zooKeeperHostList = '123.456.789.012:1234';'123.456.789.013:1234'
   clusterIndexPrefix = 'myHost-Instance1'
}

Configures the Solr6 search service in IS7.

 

 (tick) 

Tomcat servlet container

(Gradle Tools 2.0)

Structure:

tomcat {
instances {
instanceName {
port = <HTTPPORT>
securePort = <HTTPSPORT>
shutdownPort = <SHUTDOWNPORT>
}
}
}

Example:

tomcat {
instances {
server0 {
port = 80
securePort = 443
shutdownPort = 9001
}
}
}

Configures tomcat servlet container instances.

Each instance is extensible and may be marked for specific use cases, e.g. Solr search server configuration below.

   

Java VM settings

(Gradle Tools 2.0)

Structure:

tomcat {
instances {
instanceName {
jvmArgs {
minHeapSize = <SIZE>
maxHeapSize = <SIZE>
 additionalJvmArgs = ['ARG1', 'ARG2']
}
}
}
}

Example:

tomcat {
instances {
instanceName {
[...]
jvmArgs {
maxHeapSize = 1024
 additionalJvmArgs = ['\\u0022-XX:MaxPermSize=256m\\u0022']
}
}
}
}

Configures the Java VM used to start the servlet container instances.

Allows configuration of memory settings (in MB) and directly passing in additional arguments.

In case of additionalJvmArgs containing a equal sign, use unicode-encoded double quotes

   

3.3.4 Config DSL Block for Service Discovery (Gradle Tool 2.11)

Within ICM 7.8 the microservices were introduced. These and other ICM components (application server, the solr server, web adapter agent) may register at a eureka server. This enables the micro-services to find the appserver (and vice versa) and a recurring order can be triggered.

The following table is valid from IS 7.8.0.1 and shows which extensions need to be added and configured for the different host types:

Configuration ExtensionDescriptionExample

hostType

share

hostType

webserver

hostType

discoveryserver

hostType

microservices

local eureka server deploymenteurekaProvides the possiblity to install a local eureka server.eureka {     serverHostName = '127.0.0.1'     serverPort = '12345'     serverUrlPath = 'eureka/' }  (tick) 
eureka registration urleurekaThe url, which clients use to register at eurekaeureka {     serviceUrls.default = 'http://127.0.01:12345/eureka/' }(tick)(tick) (tick)
serviceAppNameappserverThe name the application server is using to register at eureka.appserver{     serviceAppName = 'appServerName'    }(tick)(tick) (tick)

microservices:

general

configuration

microservicesThe configuration of the microservices. It contains information about the database connection, the port the microservices are running and the name the microservices are using to register at eurekamicroservices {     port = '<MY_PORT>'     name = 'microserviceName'     instanceId= 'microserviceInstanceId'                   configProperties[ 'javax.persistence.jdbc.url' ]  = '<CONNECTION_URL_DATABASE>'     configProperties[ 'javax.persistence.jdbc.user' ]  = '<DATABASE_USER>'     configProperties[ 'javax.persistence.jdbc.password' ]  = '<DATABASE_PASSWORD>'       (tick)

mircroservice:

naming mapping

microservicesIt contains information about the names of the microservices.configProperties[ 'intershop.naming.service.RecurringOrder' ] = 'microserviceName'     configProperties[ 'intershop.naming.service.Scheduling' ] = 'microserviceName' }(tick)  (tick)

For further information, please refer to the following recipes:

4 Recipe: Configure Cartridge Location

Info

This recipe is valid from Gradle Tools version 2.0 and Intershop Commerce Management version 7.5.0.0.

4.1 Problem

I do not want to deploy cartridges into the shared directory. How can I deploy cartridges to a custom location?

4.2 Solution

You can change the location where cartridges are deployed, e.g., into the IS_HOME directory.

Moving the cartridge location across host types (e.g., from share to appserver) is not a deployment configuration, but requires modification of host types during the build of your assembly, see Concept - Gradle Assembly Tools.

4.3 Discussion

4.3.1 Default Locations

In your Assembly's build.gradle file the includeCartridges flag of a host type controls, whether cartridges will be deployed for this particular host type. By default, this flag will only be true for host type share (and therefore also for all).

To move cartridges from IS_SHARE to IS_HOME, you need to

  • Set includeCartridges=true for host type appserver
  • Set includeCartridges=false for host type share

This will

  • for IS_HOME
    • Deploy cartridges (including the cartridgelist) into IS_HOME/cartridges
    • Configure the cartridge location inside intershop.properties
  • for IS_SHARE
    • Not deploy cartridges into IS_SHARE/system/cartridges
    • Still deploy the cartridge's share artifacts (like static content of the sites folder) into IS_SHARE
    • Configure the cartridgelist location inside the configuration.xml

4.3.2 Custom Cartridge Location

If you do not want your cartridges to reside in either IS_SHARE/system/cartridges or IS_HOME/cartridges, you can specify a custom cartridge location inside your deployment's settings.gradle script. You still need to adjust the host type's flags according to the previous section.


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

Configure custom cartridge location
target {
    cartridgesPath = '$PLACEHOLDER/relative/path/to/cartridges'
}

In case the cartridges are going to reside on

  • The same host type, that is to be deployed (e.g., deployment of host type "appserver" with cartridges in IS_HOME/custom/cartridgeLocation), the placeholder will be resolved as follows:
    • ${IS_HOME} will become target.localDirectory
    • ${IS_SHARE} will become target.shareDirectory
    • Other placeholders will not be handled.
  • A different host type, than the one being deployed (e.g., deployment of host type "share" with cartridges in IS_HOME/custom/cartridgeLocation), the placeholder is used as reference to the foreign location.

Note

Cluster Configuration

The cartridge location must be uniform inside your cluster!

  • The cartridges must reside either in IS_SHARE or IS_HOME, you must not mix inside a cluster.
  • If the cartridges are hosted locally for each appserver, the path relative to IS_HOME must be the same for all appservers.

5 Recipe: Configure Cartridge Location via settings.gradle

Info

This recipe is valid from Intershop Commerce Management version 7.8.0.0.

5.1 Problem

There is an own settings.gradle for each host type. According to an already created ivy.xml the cartridges are deployed to the <IS_SHARE> directory, but we want the cartridges within <IS_HOME>.

Prefer the solution Recipe - Configure Cartridge Location, if possible.

5.2 Solution

  1. Remove the cartridges from share.
    Add includeCartridges = false to the target extension of the settings.gradle for host type share.
  2. Add the cartridge to local.
    Add hostType.includeCartridges = false to the host type extension of the settings.gradle for host type appserver.

5.3 Discussion

The ivy.xml, which the deployment is based on, shows the cartridges that should be deployed for host type 'share', which means they are deployed into <IS_SHARE>:

ivy.xml
...
    <e:hostType name="appserver" includeCartridges="false" includeShare="false" includeLocal="true" includeJavadoc="false"/>
    <e:hostType name="share" includeCartridges="true" includeShare="true" includeLocal="false" includeJavadoc="false"/>
...

To adapt the deployment locations to <IS_HOME>, the settings.gradle of the host type 'share' and 'appserver' need to be adapted:

settings.gradle of host type appserver
        hostType {
            hostType 'appserver'
			hostType.includeCartridges = true
        }
settings.gradle of host type share
        target {
            includeCartridges = false
        }

6 Recipe: Configure Encryption

Since Gradle tools Version >= 2.0.

6.1 Problem

Intershop 7 can encrypt sensitive database content. To decrypt data the same algorithm and key has to be used like for encryption.

Also it must be possible to use a different algorithm/key starting with a certain point in time to increase security.

6.2 Solution

Encryption is configured in three files:

  1. A properties file containing a list of encryption configurations (default name: encryption.properties). Each has an ID, an algorithm to use for generating a key and encryption.
  2. A keystore file containing a key for each encryption configuration (default name: intershop.keystore).
  3. A random file containing a fixed number of random bytes (default name: random).

One of the encryption configurations in the properties file is marked as default configuration. It is used for all encryption processes. Other encryption configurations are used to decrypt data that was encrypted when that configuration was default.

The keystore is protected against unwanted reading and writing by a password. The password is calculated from several different pieces of data. One of them is contained in the properties file, another is the content of the random file.

These three files are provided as input files to the deployment. Like other deployment input files, they become part of the desired state and should be kept under management of an external tool (like a VCS) to be able to restore them on machine failure. Encryption configuration is not modified, but only read by the application (Intershop 7).

Configuring encryption consists of two parts:

  1. Create and modify encryption configuration files. This includes specification of algorithms to use, renewal of keys and keystore password. Encryption configuration can be created/modified during or before the deployment (like in a standalone Gradle script).
  2. Deploy encryption configuration files to the shared file system of Intershop 7.

See discussion for details.

6.3 Discussion

6.3.1 Create Or Modify Encryption Configuration

The tasks described in the following sections are provided by the EncryptionAdminPlugin.

They can be executed using a settings.gradle for deployment. Also, you can run them from a standalone Gradle script, applying the EncryptionAdminPlugin:

build.gradle
buildscript {
    dependencies {
        classpath 'com.intershop:deployment-bootstrap:+'
    }
}

apply plugin: com.intershop.deploy.encryption.EncryptionAdminPlugin
                
encryption {
    propertiesFile = file('encryption.properties')
    keystoreFile = file('intershop.keystore')
    randomFile = file('random')
    algorithm = 'PBEWithMD5AndTripleDES'
}

The above example stores/loads the encryption configuration files in the same folder as the build.gradle file. You may specify a different location by setting propertiesFilekeystoreFile and randomFile to different Java File objects, e.g., propertiesFile = new File('/home/is7admin/encryption.properties').

When executing the tasks during deployment, the files are by default expected in the same folder as the settings.gradle file, see section "Deploy Encryption Configuration" below.

The algorithm property in the encryption block specifies both,

  1. which encryption algorithm to use to generate a key from a password and
  2. encrypt plain text with.

It must be of the form PBEWith<digest>And<encryption>, see Standard Algorithm Name Documentation for JDK 8 or JDK 7, depending on your version.

6.3.1.1 Create Encryption Configuration

To create the encryption configuration files initially, including a new encryption configuration and key, run the Gradle task generateEncryptionConfig. This task is called automatically as part of the normal deployment.

The generateEncryptionConfig task is idempotent:

  • It creates encryption configuration files if they are missing in the specified location.
  • It adds a new encryption configuration, if the current default encryption configuration uses a different algorithm than the one specified in the algorithm property.
  • Otherwise it leaves encryption configuration files untouched.

This ensures that after running this task there is always a valid encryption configuration using the specified algorithm, but existing database content can still be decrypted.

6.3.1.2 Change Algorithm

To use a different encryption/key generation algorithm in future, simply:

  1. Change the algorithm property
  2. Run the generateEncryptionConfig task

6.3.1.3 Generate New Key

To generate a new key, even with the same algorithm as the current default configuration, run the Gradle task newKey.

6.3.1.4 Generate New Password for Keystore

To generate a new random password for the keystore, run the Gradle task newPassword. This changes the random file, the password data in the properties file and rewrites the keystore file using the new password.

6.3.2 Deploy Encryption Configuration Files

Encryption configuration files are deployed using the EncryptionDeploymentPlugin, applied by default. You may specify:

  1. Where the encryption configuration files reside before the deployment. By default this is the directory of the settings.gradle file using the default file names given above.
  2. Where the encryption configuration files should be deployed to. By default this is in <IS_SHARE>/system/config/cluster using the default file names given above. The files must be deployed to a folder in IS_SHARE and the location is specified as relative path to that.


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

Configure Encryption
encryption {
    // Paths to the configuration files to deploy from
	// TODO: Adapt paths or remove if the defaults suffice
	propertiesFile = new File('/opt/install/encryption.properties')
    keystoreFile = new File('/opt/install/intershop.keystore')
    randomFile = new File('/opt/install/random')

	// Paths relative to IS_SHARE, that the files should be deployed to
	// TODO: Adapt paths or remove if the defaults suffice
    propertiesTargetPath = 'system/encryption/encryption.properties'
    keystoreTargetPath = 'system/encryption/intershop.keystore'
    randomTargetPath = 'system/encryption/random'
}

Note

In production make sure to limit file system permissions to the encryption configuration! This may be easier when deploying them to a different folder than <IS_SHARE>/system/config/cluster. Minimum permissions are read/write permissions for the user running deployment and application server.

If EncryptionDeploymentPlugin and EncryptionAdminPlugin are applied both (by default), encryption configuration files are automatically generated/adapted before deployment. Especially the default algorithm is changed to the algorithm configured in the encryption block, by default to the weak "PBEWithMD5AndTripleDES". To prevent the deployment from changing the encryption configuration in production, add the following line:

Disable generateEncryptionConfig task
generateEncryptionConfig.enabled = false

7 Recipe: Encrypt Database Password

Since Gradle tools Version >= 2.0.

7.1 Problem

The password that is used for connecting the Intershop 7 application with an Oracle database is stored in the <IS_SHARE>/system/config/cluster/orm.properties file. This is the default location though it is possible to change it. The password might be stored as a plain text:

orm.properties
intershop.jdbc.user=INTERSHOP
intershop.jdbc.password=intershop

If you make your shared file system accessible to a larger group of people (like your support department), but do not want to grant full database access, encrypt your database password.

7.2 Solution

  1. Create an encryption configuration and configure it to be deployed as described in the Recipe: Configure Encryption.
    Make sure to follow the best practices there (limit file permissions on encryption configuration files). If you do not do so, an attacker may gain access to your keystore and decrypt the database password.
  2. Encrypt the password using the encrypt task in a deployment or pre-deployment environment, see discussion.
  3. Use the encrypted password in the deployment's settings.gradle to the encrypted password and mark it as encrypted, see disucussion.

7.3 Discussion

7.3.1 Encrypt the Password

To encrypt the database password, run the Gradle task encrypt provided by the EncryptionAdminPlugin. It can be executed using a settings.gradle for deployment. Also, you can run them from a standalone Gradle script, applying the EncryptionAdminPlugin, see Recipe: Configure Encryption for details.

In any of the two environments, run (replacing yourPasswordInPlainText by your actual database password):

<gradle command> encrypt -PplainText=yourPasswordInPlainText

The resulting output shows your decrypted password (in the example: encryption1@PBEWithMD5AndTripleDes:5FY97GDnsvU=|3viFU8xFc1XmMhLnPXeWcVWDGgX/WUta)

:generateEncryptionConfig
:encrypt
Encrypted text for plain text 'yourPasswordInPlaintext':
encryption1@PBEWithMD5AndTripleDes:5FY97GDnsvU=|3viFU8xFc1XmMhLnPXeWcVWDGgX/WUta

(Running the command with -q will only output the encrypted password.)

Hint

Encrypting the same password over and over again always yields different results with the default algorithm. This is normal because the encryption text is salted. In this way semantic security is guaranteed.

7.3.2 Use the Encrypted Password

In the database block of your settings.gradle for the deployment as prepared in Recipe: Configure the Deployment:

  1. Specify the encrypted password in property password.
  2. Add the property passwordIsEncrypted with value true.

Given the encrypted password in the example above the result looks like this:

database block in settings.gradle
...
deploymentBootstrap {
...
    config {
    ...    
        database {
             host = 'localhost'
             port = 1521
             serviceName = 'ISORCL1.world'
             tnsAlias = 'ISSERVER.world'
             user = 'dbuser'
             password = 'encryption1@PBEWithMD5AndTripleDes:5FY97GDnsvU=|3viFU8xFc1XmMhLnPXeWcVWDGgX/WUta'
             passwordIsEncrypted = true
             oracleClientDir = new File('C:/path/to/oracle/client/dir') 
        }
    }
}

After the deployment the resulting entries in the <IS_SHARE>/system/config/cluster/orm.properties look like this:

orm.properties
intershop.jdbc.user=dbuser
intershop.jdbc.password.encrypted=true
intershop.jdbc.password=encryption1@PBEWithMD5AndTripleDes:5FY97GDnsvU=|3viFU8xFc1XmMhLnPXeWcVWDGgX/WUta

8 Recipe: Configure Mass Data Replication

8.1 Problem

I want to deploy systems, that participate in a replication environment.

8.2 Solution

  1. Use the deployment DSL to configure the data replication system type of each instance:
    1. Use none if the instance to be deployed will not participate in a replication cluster.

    2. Use editing if the instance to be deployed will only provide mass data for the replication environment.

    3. Use live if the instance to be deployed will receive mass data in a replication environment.
      This also applies if it is not the last system of a replication chain.

8.3 Discussion

Applying StagingDeploymentPlugin (which is part of IntershopPlugins) will let you configure data replication via the following DSL:

staging-related deployment configuration inside config { } Block
staging {
    systemType = 'editing' | 'live' | 'none'
    replicationClustersFile = new File('<FILL IN>')
}

This will:

  • Set the data replication system type in <IS_SHARE>/system/config/cluster/staging.properties
  • Copy the given replication clusters configuration file to <IS_SHARE>/system/config/cluster/ if provided. This file is only required for editing systems.
  • For live systems:
    • Since Gradle Tools 2.0:
      • Files in <IS_SHARE>/sites/*/1 will also be deployed to <IS_SHARE>/sites/*/2
      • Staged content in <IS_SHARE>/sites/*/[1,2] (including the .active flag) will not be overwritten by deployment
    • Until Gradle Tools 1.1:
      • Be aware that deployment of a live system will reset your replicated content.

        Please consider updating to a newer release of Gradle Tools. As a workaround, you may define a custom modification handling strategy as defined in the Recipe: Keep Local Modifications:

        keep('stagedFiles') {
        	priority '<YourPriority>'
        	dir project.target.shareDirectory
        	include 'sites/*/?/**'
        	include 'sites/*/.active'
        	include 'system/config/cluster/solr/solr.xml'
        }

9 Recipe: Set Up Project Based on the Responsive Starter Store

9.1 Problem

Starting with Intershop Commerce Management Suite 7.6 (B2C, B2X) the delivered assemblies no longer include cartridges that define the storefront applications and do not provide the storefront functionality, meaning the view layer with the content model. Instead, Intershop provides the Responsive Starter Store. This includes the storefront parts as a source project that can be used as a blue print to set up customer projects.

After creating the project source structure from the Intershop templates it is necessary to fill the project with the specific artifacts, especially those that make up the storefront. The Responsive Starter Store is a good starting point, that provides the functionality, code artifacts and demo content of a standard responsive storefront.

How can a build engineer or developer set up a project based on the Responsive Starter Store?

9.2 Solution

9.2.1 Prerequisites

Note

License

Please make sure to comply with Glyphicons Free license terms (CC BY 3.0) or get pro license.

See the following recipes:

9.2.2 Steps

Note

The following listings contain diff-style where "<DIFF>" leads the listing title.

This describes changes on files where "-String=original line of code;" represents the original line of code that should be replaced with "+String=replaced line of code'".

  1. Download the latest version of the Responsive Starter Store (Version 3.+).
    If you want use the latest version of Gradle Tools with Responsive Starter Store Version 1.+ or 2.+, please use the migration steps from Public Release Notes - Gradle Tools - Version 2.11.
  2. Copy the contents of the Responsive Starter Store multi-project into your project folder, e.g., corporateshop.
  3. Set up the initialization cartridges.
  4. Commit changes to your VCS.

See the following sections for details.

9.2.3 Download the Latest Version of the Responsive Starter Store

Note

Newer versions of the responsive starter store

Find the Responsive Starter Store version and download links for a corresponding Intershop Commerce Management version in the Reference - CI Dependencies of Intershop Commerce Management.

Responsive Starter Store version 3.1.4 for Intershop Commerce Management 7.8:

  • Download the Responsive Starter Store multi project (a_responsive).

    Responsive Starter Store - Component Set
    http://<your-reposerver:port>/nexus/content/repositories/ishrepo/com.intershop.public.source/a_responsive/3.1.4/zips/a_responsive-zip-src-3.1.4.zip

    or from Intershop public repository

    https://repository.intershop.de/releases/com.intershop.public.source/a_responsive/3.1.4/zips/a_responsive-zip-src-3.1.4.zip

Responsive Starter Store version 4.0.0 for Intershop Commerce Management 7.9

  • Download the Responsive Starter Store multi project (a_responsive).

    Responsive Starter Store - Component Set
    http://<your-reposerver:port>/nexus/content/repositories/ishrepo/com.intershop.public.source/a_responsive/4.0.0/zips/a_responsive-zip-src-4.0.0.zip

    or from Intershop public repository

    https://repository.intershop.de/releases/com.intershop.public.source/a_responsive/4.0.0/zips/a_responsive-zip-src-4.0.0.zip

9.2.4 Copy the Contents of the Responsive Starter Store Source Package into the Projects Folder

Content Overview of the Responsive Starter Store multi project:

a_responsive
|-- app_sf_responsive
|-- app_sf_responsive_b2b
|-- app_sf_responsive_b2b_test
|-- app_sf_responsive_b2c
|-- app_sf_responsive_cm
|-- app_sf_responsive_costcenter
|-- app_sf_responsive_smb
|-- app_sf_responsive_test
|-- as_responsive
|-- as_responsive_b2b
|-- demo_responsive
|-- demo_responsive_b2b
|-- demo_responsive_catalog
|-- demo_responsive_content
|-- demo_responsive_ocst
|-- demo_responsive_search
|-- dev_storefront
|-- gradle
|-- inspired-b2c
|-- inspired-b2x
|-- microservices
|-- .ivyIcm-b2c.version
|-- .ivyIcm-b2x.version
|-- build.gradle
|-- gradle.properties
|-- gradlew
|-- gradlew.bat
`-- settings.gradle
responsive starter store
base storefront cartridge
additional B2B functionality cartridge
automatic tests for B2B functionality
base storefront cartridge
base storefront cartridge
additional B2B functionality cartridge
base storefront cartridge
automatic tests for base functionality
base storefront cartridge
additional B2B functionality cartridge
demo content cartridge
additional B2B demo content cartridge
demo content cartridge
demo content cartridge
demo content cartridge
demo content cartridge
development cartridge
 
B2C demo assembly
B2X demo assembly
micro-services scheduling and recurring orders 
version file for ICM b2c (Available with ICM 7.9)
version file for ICM b2x (Available with ICM 7.9)

Place the content into the working copy of your project folder (that was generated via CI bootstrap before). Rest assured that there are no conflicting files in your projects folder that otherwise need to be overwritten.

Long path names on Windows

On Windows certain tools have trouble dealing with path names longer than 255 characters. When in doubt, please use 7-Zip 15.12 or newer to uncompress the source packages.

9.2.5 Adapt the Build Configuration of the Responsive Starter Store Source Package

After copying the contents of the a_responsive Gradle multi-project set into your project folder some files need to be changed to fit your projects configuration.

  • Replace a_responsive with your projects name in the following files

    <DIFF> settings.gradle
    // define root project name
    -rootProject.name = 'a_responsive'
    +rootProject.name = 'corporateshop'
  • Replace the com.intershop.responsive group with your projects group in the following file:

    <DIFF> build.gradle
    description 'Components Responsive Starter Store Applications'
    -group = 'com.intershop.responsive'
    +group = 'com.company.corporateshop'
    
    subprojects {
    -   group = 'com.intershop.responsive'
    +   group = 'com.company.corporateshop'
  • Adapt the release configuration of the project. 

    <DIFF> build.gradle
    // ci configuration
    -	/**
    -	 * Intershop release configuration
    -	 * requires
    -	 *  - Sonatype Nexus Pro with a configured staging configuration
    -	 *  - Atlassian Jira
    -	 *  and additional environment variables.
    -	 * Furthermore an applied SCMVersion plugin is mandatory.
    -	 * See https://github.com/IntershopCommunicationsAG/gradle-release-plugins.
    -	 **/
    -	apply plugin: 'com.intershop.gradle.nexuspublish-configuration'
    -   apply plugin: 'com.intershop.gradle.artifactorypublish-configuration'
    /**
     * Simple Release configuration
     * requires only a Maven compatible repository and
     * additional environment variables.
     * See also https://github.com/IntershopCommunicationsAG/gradle-release-plugins. 
     **/
    -	// apply plugin: 'com.intershop.gradle.simplepublish-configuration'
    +	apply plugin: 'com.intershop.gradle.simplepublish-configuration'
    -	/**
    -	 * This plugin will create a source package of the build.
    -	 * It is possible to use this e.g. for the creation of an ESCROW package.
    -	 * _This plugin is optional._
    -	 * See https://github.com/IntershopCommunicationsAG/gradle-release-plugins
    -	 **/
    -	apply plugin: 'com.intershop.gradle.escrow-plugin'
    -	escrow {
    -    	sourceGroup = 'com.intershop.public.source'
    -	    exclude '*/target'
    -	    exclude '**/gradle/wrapper/gradle-wrapper.properties'
    -	}
     
    description 'Components Responsive Starter Store Applications'
    group = 'com.intershop.responsive'
    assert System.properties['java.version'].startsWith('1.8')
    
    
    - artifactory {
    -     publish {
    -         // for ivy publications
    -         repository {
    -             maven = false
    -         }
    -         // list of publication names
    -         defaults {
    -             publications('ivy', 'ivyEscrow')
    -         }
    -     }
    - }
     
  •  Replace the version number with a version number fitting to your projects.
    1. Intershop Commerce Management 7.8
      Change the Intershop Commerce Management version in the following file:

      <DIFF> gradle.properties
      # dependency versions
      -version.com.intershop.assembly.commerce_management_b2x = 7.X.0.0
      +version.com.intershop.assembly.commerce_management_b2x = 7.X.X.X
      -version.com.intershop.assembly.commerce_management_b2c = 7.X.X.X

      If you need only Intershop Commerce Management B2C use b2c instead of b2x:

      <DIFF> gradle.properties
      # dependency versions
      -version.com.intershop.assembly.commerce_management_b2x = 7.X.0.0
      -version.com.intershop.assembly.commerce_management_b2c = 7.X.X.X
      +version.com.intershop.assembly.commerce_management_b2c = 7.X.X.X
    2. Intershop Commerce Management 7.9
      With this version we introduced a better plugin for the version handling. See https://github.com/IntershopCommunicationsAG/versionrecommender-gradle-plugin
      Therefore the files .ivyIcm-b2c.version or .ivyIcm-b2x.version must be changed. Replace the version in these files with your own.
  • Remove not needed sub projects.
    (warning) Do not skip this step! You really need to delete these folders, otherwise you will run into exceptions.

    Assembly TypeStorefront CartridgesDemo/Init CartridgesAssembly
    B2Capp_sf_responsive
    app_sf_responsive_cm
    app_sf_responsive_b2c
    app_sf_responsive_smb
    as_responsive
    demo_responsive
    demo_responsive_catalog
    demo_responsive_content
    demo_responsive_search
    demo_responsive_ocst
    inspired-b2c
    B2XB2C Storefront Cartridges + app_sf_responsive_b2b
    app_sf_responsive_costcenter
    as_responsive_b2b
    B2C Demo/Init Cartridges +
    demo_responsive_b2b
    inspired-b2x

    The table gives an overview of the needed cartridges for the different assembly types.

  • Rename the folder of the assembly sub project 'inspired-b2x' or 'inspired_b2c' to your preferred name, e.g., assembly_corporateshop. This name is used for the deployment of the project.

  • Adapt build configuration for the used assembly

    If a B2C assembly will be created:

    <DIFF> build.gradle
    assert System.properties['java.version'].startsWith('1.8')
     
    -	def assemblyProjects = [ project(':inspired-b2c'), project(':inspired-b2x') ]
    +	def assemblyProjects = [ project(':assembly_corporateshop') ]

    If a B2X assembly will be created:

    <DIFF> build.gradle
    assert System.properties['java.version'].startsWith('1.8')
     
    -	def assemblyProjects = [ project(':inspired-b2c'), project(':inspired-b2x') ]
    +	def assemblyProjects = [ project(':assembly_corporateshop') ]

    This configuration does only exists in version 3.x (ICM 7.8).

    build.gradle
        buildDir = new File(projectDir, 'target')
    -    if(name == 'inspired-b2x') {
    -        versioning {
    -            useVersionsFrom 'com.intershop.assembly:commerce_management_b2x'
    -        }
    -     }
    -    if(name == 'inspired-b2c') {
    +	 if(name == 'assembly_corporateshop') {
            versioning {
                useVersionsFrom 'com.intershop.assembly:commerce_management_b2x'
            }
        }
    
    

9.2.6 Setup the Initialization Cartridges

The Responsive Starter Store provides a set of demo cartridges that can be kept as starting point for the projects initialization cartridges or they can be removed completely.

CartridgeDescription
demo_responsiveDemo organization structure for inSPIRED with inTRONICS, inTRONICS Business and Myers
demo_responsive_catalogCatalogs with categories and products for the inSPIRED organization
demo_responsive_contentCMS demo content (including campaigns and promotions) for the inSPIRED organization
demo_responsive_searchSearch demo configuration
demo_responsive_ocstAdditional demo content of the OCST (Omni-channel Services Toolset, a.k.a. Contact Center)
demo_responsive_b2bB2B specific content for the inTRONICS Business channel

In case they are used as init cartridges it is probably useful to rename the cartridges from "demo_..." to "init_..." or some other project naming scheme.
The renaming needs to be done for the cartridges folder name of the cartridge. The display name and description of the cartridge can be renamed in the build.gradle.

9.2.7 Setup the Intershop Microservices

The Responsive Starter Store provides a sub-project microservice, which contains the microservices scheduling and recurring order.

Database for microservices

It's mandatory for production system to replace the Derby Database. Therefore the build.gradle of the microservice sub-project has to be adapted

For Oracle it is necessary to configure the correct database driver. If you have this driver in an other group, please adapt the configuration.

build.gradle
dependencies {

    /** driver for derby */
    - runtime 'org.apache.derby:derby:10.12.1.1'
    /** driver for oracle */
    /** this configuration uses the prepared oracle drivers **/
    /** see 'Cookbook - Setup CI Infrastructure', 7.2.5 Process for Building the Oracle JDBC Drivers Component **/
    + runtime 'com.oracle.jdbc:ojdbc7:12.1.0.2.0.0'
}

9.2.8 Extend the 'ignore' Configuration

During the build of same cartridges CSS files will be generated with a Less compiler. These files must be generated to staticfiles/cartridge/static/default/css. Therefore it is necessary to extend the ignore configuration for these cartridges.

Cartridge with less compiler configuration
app_sf_responsive
app_sf_responsive_b2b
app_sf_responsive_smb

9.2.8.1 Subversion

It is possible to add svn:global-ignores for the project directory:

svn:global-ignores
theme.css
theme.css.map

or add svn:ignore to <cartridge name>/staticfiles/cartridge/static/default/css:

svn:ignore
theme.css
theme.css.map

9.2.8.2 Git

Extend .gitignore of the root project:

.gitignore
# IntelliJ project files
.idea
*.iml
out
gen
*.bak
*.log

# Eclipse project files
**/bin/
**/.settings/
**/.classpath
**/.project

# editor backup files
**~

# Gradle Files
**/build/
**/.gradle

# Intershop build directories
**/target/
# Ignore Gradle GUI config
gradle-app.setting
 
# generated css
app_sf_responsive*/staticfiles/cartridge/static/default/css/themes.css
app_sf_responsive*/staticfiles/cartridge/static/default/css/themes.css.map
app_sf_responsive*/staticfiles/cartridge/static/default/css/


# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar

9.2.9 Commit the Changes to the VCS

After the changes it is necessary to commit the changes to the used VCS and transfer the files to the remote server.

9.3 Discussion

9.3.1 Different Options of Customizing the Responsive Starter Store

As mentioned earlier, the demo cartridges of the Responsive Starter Store can be used as blue print for the projects initialization cartridges. For that they should be renamed and fitted to your projects needs.

Regarding the storefront cartridges of the Responsive Starter Store (app_sf_responsive, app_sf_responsive_cm, ...) there are several options on how you can use and customize them in your projects. Those options are described below.

In any case it might be necessary to not only adapt the app_sf_responsive cartridges but also the application type definitions of as_responsive. If additional project cartridges are added they need to be added to the application type definition too.

9.3.1.1 Use Responsive Starter Store Cartridges As Is

This is the above described approach of copying the relevant storefront cartridges of the Responsive Starter Store to your projects.

Any customization can be done within additional project cartridges, with the possibilities overloading and overwriting provides. This is pretty much the same as before, except for the fact that also the Responsive Starter Store storefront cartridges are part of the project cartridges set.

This fact, that the Responsive Starter Store storefront cartridges are part of your projects sources, leads to the second customization option. It is now possible to make any customization directly in the cartridges that were provided by Intershop since they are now project cartridges. You have pretty much the same control over these sources as an Intershop developer has when developing the Responsive Starter Store. Any parts can be changed or removed or added within the cartridges of the Responsive Starter Store. This gives you for example full control over the provided CMS content model, making it possible to simply add new call parameters where needed or removing not wanted components without the need of using the overwrites mechanism.

Using the Responsive Starter Store storefront cartridges as they are is probably the simplest approach. And in case the customization is done within additional project cartridges this is probably the easiest approach for later migrations to new Responsive Starter Store versions too.

In any case newer versions of the Responsive Starter Store cartridges are not getting updated automatically but will be provided as sources too and it is up to the project to decide if and how they will update their currently used Responsive Starter Store cartridges. Less customization in those cartridges will probably make the update/migration easier.

9.3.1.2 Copy and Rename the Responsive Starter Store Cartridges

The Responsive Starter Store is intended to be a blue print for a storefront project. The provided cartridges can be used the way they are regarding their naming and their content or they can be customized in any way wanted.

In case you want to create several independent application types that are initially based on the Responsive Starter Store or if you want to create your own storefront cartridge set based on the Responsive Starter Store but with your own naming conventions, you have to copy and rename the app_sf_responsive cartridges to transform them them into your own cartridges.

For this you basically have to search for all references to app_sf_responsive and alike in the Responsive Starter Store cartridges and replace all with your own cartridge naming. This goes for references in the content model files (*.pagelet2), in pipelines, in ISML templates and configuration files.

Also the CMS import files located in sites folder of demo_responsive_content need to be adapted to the new naming.

After this everything should work as before but with the new naming.

9.3.1.3 Use Own Storefront Cartridges

In case you want to use or create your own storefront cartridge set that is totally different from the Responsive Starter Store you can also remove the app_sf_responsive cartridges completely from your project. In that case you might only use the configuration files of the Responsive Starter Store but not the cartridges to set up your project.

You would build your storefront only on the basic storefront functionality that is provided by the Commerce Management assembly you are using. Basically this gives you only the storefront functionality of the sld_ch_sf_base cartridge. The whole storefront view layer would need to be provided by your own cartridges.

9.3.2 Release Process Configuration and Versioning

Internally, Intershop uses an release process with staging for releases, so that unused milestone builds can be easily dropped. For reporting purposes all issues will be extended with the solved version during the build process. Furthermore the version of internal Intershop projects is calculated from used source repository (see https://github.com/IntershopCommunicationsAG/scmversion-gradle-plugin.) This plugin is required by the release plugin com.intershop.gradle.nexuspublish-configuration. It is also possible to use a version in a property file. In this case the configuration for the com.intershop.gradle.scmversion plugin can be removed.

During the build of same cartridges CSS files will be generated with a less compiler. It is necessary, that these files must be generated to staticfiles/cartridge/static/default/css. Therefore it is necessary to extend the ignore configuration for these directories.

10 Recipe: Run the Deployment (Initial Installation / Upgrade / Downgrade)

10.1 Problem

I want to run the deployment.

10.2 Solution

To deploy an assembly execute the following steps:

  1. Prepare and configure your environment.
    See Recipe: Prepare the Deployment and Recipe: Configure the Deployment for details.
  2. Create the target user.
  3. Execute the Gradle task for the deployment.

10.3 Discussion

10.3.1 Initial installation / Upgrade / Downgrade

The workflow for initial installation, upgrade, downgrade is always the same.

The only difference is the used assembly (version) in your settings.gradle file. The deployment automatically handles if there is already a version available in the target directory and deploys the difference.

10.3.2 Create a User

The deployment will not create any users on your target system. Therefore, you have to create a user. This users can execute the deployed system. It is the same user that can run the deployed application.

If you want to run different applications like the webserver and the application server on different hosts, you have to run multiple deployments from multiple settings.gradle files.

The user name and group must be declared in the settings.gradle file, see Recipe: Configure the Deployment or Recipe: Configure the Deployment (valid to 7.8), depending on your version. This allows for a validation that the current user intends to run the deployment. Also the user will run the Windows services. 

The user must have permissions to create files and directories in the directory of the settings.gradle script, as well as IS_SHARE and IS_HOME as configured in the settings.gradle.

10.3.3 Execute Deployment

To execute the deployment:

  1. Log in as the user mentioned above and
  2. Execute the following command:

    <gradle command> deploy

10.3.4 Post Install

There are some operations which require root/administrator privileges. For those operations, the deployment creates a post install script. The post install script(s) are listed at the end of the deployment:

------------------------------------------------------------------------------------
To finish the deployment please execute the following scripts as administrator /
with root privileges: 
/folder/postInstall/installServices.sh
------------------------------------------------------------------------------------

10.3.5 Logging

Gradle does not support writing log output to a file. Use console redirection or the Linux tee command. See also Gradle user guide on Logging (2.11, 2.72.32.01.8).

11 Recipe: List All Deployed Resources

Since Gradle Tools Version >= 2.1.

11.1 Problem

I want to get more information about my deployed instance.

11.2 Solution

The Gradle task listing will create a file listing.txt containing information about all the deployed resources and their current state.

11.3 Discussion

The resulting output file may be quite large, therefore mind some hints:

  • All entries are sorted alphabetically by resource name, i.e., absolute path of files.
  • There is no integrated query functionality, but the entry format is held simple enough to enable easy filtering. Use any filtering tool (like grep) to get only the information you are looking for.

The general syntax for each entry is as follows:

Flags  ResourceName [AdditionalInformation]
  • Flags contains the following:
    1. The first position marks the current state of the resource. The symbol displayed is similar to the output of svn status:
      • ' ' (space) unmodified
      • M modified
      • ! missing
      • ? unknown (file has not been created by the deployment)
      • ~ different type (e.g., there is a directory instead of a file)
    2. More flags may be added in future versions.
  • Additional information may contain:
    1. (:project:taskName) the task that deployed this resource. (Only if the state flag does not indicate unknown)
    2. A human readable description of the local modification. (Only if the state flag does not indicate unmodified)
    3. More notes may be added in future versions.

12 Recipe: (Windows) Starting a Service Fails

12.1 Problem

On Windows starting one of the services fails. There are (at least) two kinds of problems here:

  1. Log on failure. The according error message is:

    Windows could not start the <service name> service on Local Computer.
    
    Error 1069: The service did not start due to a logon failure.
  2. Service-specific failure. The according message is:

    Windows could not start the <service> on Local Computer. For more information, review the System Event Log. If this is a non-Microsoft service, contact the service vendor, and refer to the service-specific error code <error code>.

12.2 Solution

12.2.1 Logon Failure

Typical problems causing this message are:

  1. The password you entered in the post-install scripts was wrong.
  2. The Log on as a service right is not granted to the executing user.

In both cases the following procedure solves the problem:

  1. Open the Windows services dialog (services.msc).
  2. Right-click the service.
  3. Choose Properties from the context menu.
  4. Switch to tab Log On.
  5. Re-enter the password.
  6. If the user did not have the Log on as a service permission, it will automatically be granted -
    a message will be shown: The account <account> has been granted the Log On As A Service right.
  7. Start the service.

12.2.2 Service-specific Failure (Port Blocked)

The most typical reason for a service-specific failure (after an otherwise successful deployment) is that local ports are blocked by other applications. To verify this:

  1. Start the Event Viewer (eventvwr.msc).
  2. Navigate to Windows Logs/Application in the tree-view pane.
  3. Look into recent events of level Error.

The service may file multiple of such errors. The Intershop HTTP Server service reports a blocked port like this:

The Apache service named <service> reported the following error:
>>>
 (OS 10013)An attempt was made to access a socket in a way forbidden by 
its access permissions.  : AH00072: make_sock: could not bind to address
 [::]:<port>     .

To find out which application blocks the port, run the following command on the command line:

netstat -aon | find ":<port>"

The last column of the output is the process ID (which you can connect to a process name in the Task Manager).

13 Recipe: Configure Intershop 7

13.1 Problem

How to change a file based configuration of Intershop 7 as an administrator/developer, i.e., overwriting the default if any?

Examples are:

  • Properties in properties-files in <IS_SHARE>/system/config/cluster
  • Properties in properties-files in different locations, like <IS_HOME>/webadapter/webadapter.properties
  • Non-properties-file based configuration for Intershop 7, like <IS_SHARE>/system/config/cluster/replication.xml
  • Configuration of third-party products deployed with Intershop 7, like <IS_HOME>/httpd/conf/httpd.conf or <IS_HOME>/engine/tomcat/servers/appserver0/conf/server.xml

13.2 Solution

First of all the solution depends on the operational concept:

13.2.1 Edit the Files Manually After the Deployment

This is straight-forward, but has a few disadvantages (see the discussion). For this approach see the recipe Keep Local Modifications to keep the deployment from restoring the originally deployed content of configuration files.

13.2.2 Change Configuration Automatically Through the Deployment

There a few cases here:

  1. For configuration that is commonly changed the deployment DSL offers convenient ways to provide values directly in your settings.gradle file. Use it if available. See the Recipe: Configure the Deployment.
  2. The configuration is property/preference based and read through the configuration framework:
    1. Provide a file <environment>.properties next to your settings.gradle file, containing only the properties you want to override. Deploy it as an additional file to <IS_SHARE>/system/config/cluster, see the Recipe: Deploy Custom Files.
    2. Alternatively, you can modify <IS_SHARE>/system/configuration/configuration.xml to read other properties-files or preference tables from the database, see section XmlContentFilter of the Recipe: Change Deployed File Content Through Filters.
  3. The configuration file is not read by the configuration framework (like webadapter.properties or any non-properties-file).
    1. Alternatively replace the whole deployed file by your own content, see the Recipe: Replace a File Deployed by Another Component.

The administrator's effort for automatically changing configuration can reduced and moved to the developer. See the Recipe: Provide Custom Deployment Configuration and Logic.

For the special use case of changing the configuration, the following divisions of work are thinkable:

  1. If Intershop 7 default configuration is always overwritten in the same way for a certain assembly, the developer can include the deployment code in the deploy.gradle file of the assembly or custom components, releasing the adminstrator entirely.
  2. The developer can provide deployment logic in the deploy.gradle  file of the assembly/custom components that is configurable through Gradle extra project properties. The adminstrator only has to provide values for these properties in the settings.gradle file.
  3. The developer can provide custom deployment plugins and DSL extensions. He can optionally pre-apply them in the deploy.gradle file of the assembly/custom components. The adminstrator can then apply these plugins and use their DSL for configuration in the settings.gradle file.
  4. The developer can provide custom content filters, which can be used by the administrator in the settings.gradle file.

13.3 Discussion

13.3.1 Manual vs. Automatic Configuration

Editing configuration files manually after deployment is the easiest solution for disposable or low-frequency deployments. Its big disadvantage is that it cannot be repeated easily and does not help you in monitoring configuration and restoring from broken states. This is against the ideas of continuous delivery/devops, but still possible.

If you use this approach, you must configure the deployment to keep your modified versions of deployed files. The default behavior is to restore the originals on every deployment run. See the the Recipe: Keep Local Modifications.

Note

Changes introduced through the development will not make it into these files anymore, essentially omitting them from upgrades.

13.3.2 Configuration Framework

Most configuration of Intershop 7 is read through the configuration framework in forms of properties. If you want to change these properties, provide your values in an additional configuration source and make it have priority over other sources. Configuration sources and their priorities are configured in <IS_SHARE>/system/config/cluster/configuration.xml.

One kind of configuration source are properties- files. The default configuration.xml file declares to load <IS_SHARE>/system/config/cluster/<environment>.properties if it exists. Its priority is higher than most of the properties-files in <IS_SHARE>/system/config/cluster, like appserver.properties or orm.properties. The name of the file must match the environment you specify in your settings.gradle, e.g., <IS_SHARE>/system/config/cluster/production.properties for environment 'production'.

To add additional configuration sources, you may use the XmlContentFilter, see section XmlContentFilter of the Recipe: Change Deployed File Content Through Filters.

 

14 Recipe: Provide Custom Deployment Configuration and Logic

14.1 Problem

Where to declare deployment configuration and custom logic?

14.2 Solution

Provide deployment configuration and logic by settings properties/calling methods on a Gradle Project object and the DSL extensions attached to it. Developers and administrators can do so in different places. As described in the Concept - Gradle Deployment Tools, there is a hierarchy of Project objects. The root Project represents the assembly itself, while all child Project objects represent components included in the assembly.

Code snippets in this cookbook, unless stated otherwise, can be put in any of these locations:

  1. As an administrator use the deploymentBootstrap.config block inside the settings.gradle file of the deployment.

    Configure Project in settings.gradle
    ...
    deploymentBootstrap {
    	...
    	config {
    		// configure the root project here
    		// for configuring child projects, see discussion
    	}
    }
  2. As a developer use the deployment/deploy.gradle file of your custom components for configuration and deployment that your component requires.

    Note

    The behaviour of the deployment changes depending on whether a deploy.gradle script is provided or not. When you do not provide a deploy.gradle, the CartridgeDeploymentPlugin is applied by default.

    If you do provide a deploy.gradle, only its content will configure deployment for the according component. If you want to retain the previous behaviour, you have to include the following snippet into your deploy.gradle:

    Cartridge Deployment with Custom deploy.gradle
    apply plugin: com.intershop.deploy.cartridge.CartridgeDeploymentPlugin
  3. As a developer use the deploy.gradle file of your assembly for configuration that cannot be associated to a single component or that is only required in the deployment of that assembly, instead of all assemblies that might include that single component. See the Recipe: Add Custom Deployment Logic to an Assembly or Recipe: Add Custom Deployment Logic to an Assembly (valid to 7.8), depending on your version, for details.

  4. As a developer use an additional init.gradle script in your Gradle user home for configuration that is specific to your developer environment. (The settings.gradle file is generated for developers and should not be edited manually.)
  5. As a developer provide custom deployment plugins for reusable pieces of deployment configuration/logic.
  6. As a developer or administrator apply a custom or third-party deployment plugin in any of the above locations.

Some pieces of deployment data are only known by the administrator at deployment time (like paths and ports). The deployment logic/configuration provided by the developer can read these pieces of data from logic/configuration provided by the administrator in the following ways:

  1. Through extra Project properties for simple data types and small amounts of data.
  2. Through Custom DSL extension objects for complex data structures or larger coherent data sets.

14.3 Discussion

See also chapter Multi-project Builds in the Gradle User Manual (2.11, 2.72.32.01.8).

14.3.1 Configuring Different Projects

Each of the above mentioned locations by default configures a certain Project. The following listings describe that default Project object and show how to configure other Project objects.

Gradle projects are always accessed by their path. The path of the root project is the colon ':', the path of other projects is a colon followed by the (unqualified) name of the associated component: :<component name>, e.g., :bc_foundation.

The use of Gradle's afterEvaluate is explained in the next section.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// configure the root project here
		
		// To configure a child project:
		if (findProject(':<component name>') {
			project(':<component name>') {
				afterEvaluate {
					// configure the child project here
				}
			}
		}
	}
}

For developer deployments (for which settings.gradle is generated and not subject to manual editing) add a Gradle init script:

<GRADLE_USER_HOME>/init.d/<any name>.gradle (Init script)
settingsEvaluated { Settings settings ->
    if (!settings.extensions.findByName('deploymentBootstrap')) {
        // Not a deployment
        return;
    }
        
    settings.deploymentBootstrap {
        config {                
            logger.lifecycle('Applying custom deployment configuration from: ' + initscript.sourceFile)

            //Write any configuration that can be specified
            // in the config-Block of the settings.gradle         
            // this is like appending it to the actual settings.gradle
            // (i.e. it will be executed after the config block of the settings.gradle)                       
        }
    }  
}
<assembly>/deploy.gradle (since 2.11.x)
// configure the root project here

// To configure a child project:
if (findProject(':<component name>') {
	project(':<component name>') {
		afterEvaluate {
			// configure the child project here
		}
	}
}

For Gradle tools version 1.0 - 1.1:

<cartridge>/deployment/deploy.gradle
// configure the project associated with the component here

// To configure another child project:
if (findProject(':<component name>')) {
	project(':<component name>') {
		def configClosure = {
			// configure the other child project here
		}

		if (project.state.executed) {
	        configClosure()
		} else {
	        afterEvaluate(configClosure)
		}
	}
}

// To configure the root project:
project(':') {
	// configure the root project here
}

For Gradle tools version >= 2.0:

Each project has the method evaluatedProject to which you pass in a closure. If the project is already evaluted the closure will be executed immediately. Otherwise it will be executed one the project has been evaluated. This makes configuring other projects easier:

<cartridge>/deployment/deploy.gradle
// configure the project associated with the component here

// To configure another child project:
if (findProject(':<component name>')) {
	project(':<component name>').evaluatedProject {		
		// configure the other child project here
	}
}

// To configure the root project:
project(':') {
	// configure the root project here
}

Defensive Project Access

The listings above defensively access child projects, i.e., they first check if a certain project exists before trying to configure it. This is best practice for at least two reasons:

  1. If sensible it should be possible to add or remove components from an assembly without touching its deployment script.
    A component should be usable in different assemblies without being forced to include other components whose existence is assumed in its deploy.gradle file.
  2. Even if you can assume which components are included in an assembly, only some of these are deployed in a clustered environment, depending on selected host-type and environment.
  3. The same consideration applies if you want to reuse (parts of) your settings.gradle for deployment of different host-types/environments.

14.3.2 Order of Evaluation

When providing custom deployment configuration/logic in different locations the order of their evaluation is critical. Deployment configuration is mostly a three-step process distributed over different locations:

  1. Apply deployment plugins, which provide DSL extensions in the deploy.gradle scripts of a component/the assembly.
  2. Configure these DSL extensions in the settings.gradle file and/or different components/the assembly.
  3. Read the data from these DSL extensions to configure some lower-level DSL.

For example:

  1. The deploy.gradle of the assembly applies the TargetPlugin, which defines adds an extension target to the project for configuration the location of IS_HOME and IS_SHARE.
  2. The settings.gradle provides specific locations for IS_HOME and IS_SHARE by setting the properties localDirectory and targetDirectory of the target extension.
  3. The deploy.gradle of an infrastructure component uses the value of target.localDirectory to determine where to deploy its start scripts.

The following diagram shows the different locations and the order in which they are evaluated:

settings.gradle
...
deploymentBootstrap {
	...
	config {



		// Evaluation-Order: #2
		// configure the root project here

  
		


		




		
		// To configure a child project:
		if (findProject(':<component name>') {
			project(':<component name>') {
				afterEvaluate {
					// Evaluation-Order: #5
					// configure the child project here
				}
			}
		}

	}
}



deploy.gradle of the assembly
// Evaluation-Order: #1 
// configure the root project here

 
















// To configure a child project:
if (findProject(':<component name>') {
	project(':<component name>') {
		afterEvaluate {
			// Evaluation-Order: #5
			// configure the child project here
		}
	}
}






deploy.gradle of a component
// deploy.gradle script of any component









// Evaluation-Order: #3 
// configure the project associated with the component here

// To configure the root project:
project(':') {
	// Evaluation-Order: #4 
	// configure the root project here
}


// To configure another child project:
if (findProject(':<component name>')) {
	project(':<component name>') {
		def configClosure = {
			// Evaluation-Order: #5
			// configure the other child project here
		}

		if (project.state.executed) {
	        configClosure()
		} else {
	        afterEvaluate(configClosure)
		}
	}
}

The order between multiple locations with the same number is not determined. Do not rely on the order and make sure that different orders do not cause different behavior. Examples of this are:

  • Do not rely upon a certain order between the deploy.gradle scripts of different components. (This is the reason for checking the project.state first in the listing.)
  • Do not rely upon a certain order between different afterEvaluate blocks applied to the same project.

Late Evaluation of extension 'deployment'

A very important DSL extension is the ResourceDeploymentExtension attached to the property deployment of the project. It is used to deploy files, links, directories, apply content filters and create services. It is configured using the method deployment, which expects a closure. Closures passed to the deployment method are evaluated late, so they can access data specified in the settings.gradle, like the target.shareDirectory.

Example of using extension 'deployment' in deploy.gradle in assembly
deployment {            
	// Configure the ResourceDeploymentExtension here 
	// Evaluation-Order: #5 (like all afterEvaluate closures)
	// This example adds an additional property file
	files {
		additionalProperties {
            from new File('/etc/config/intershop7/additional.properties')
         
            // Define target of the copy operation
            into new File(target.shareDirectory, 'system/config/cluster/')
       	}
	}
}

14.3.3 Passing Data Through Extra Project Properties

Use extra project properties to pass in data from the settings.gradle file to deployment logic/configuration provided by development. See also Gradle DSL documentation on Project (2.112.72.32.01.8). Extra project properties can be any Java object of any type. Especially, use File, List or Map if applicable.

The following listings show how to use an extra property across the deploy.gradle file of the assembly, provided by the developer, and the settings.gradle, provided by the administrator.

deploy.gradle of assembly
...

//1. Create the extra property and set a default value (you can use null if there is none)
project.ext.additionalPropertiesFilesDir = new File('/etc/config/intershop7')








deployment {
	 //3. Use the value in a location evaluated settings.gradle
	 files {
		additionalProperties {
			
			from new File(project.additionalPropertiesFilesDir, 'additional.properties')         
            into new File(target.shareDirectory, 'system/config/cluster/')
       	}
	}
}
settings.gradle
...
deploymentBootstrap {
	...
	configure {

		
		//2. Provide a value
		additionalPropertiesFileDir = new File('/opt/intershop7/config')		
	}
}












15 Recipe: Change Deployed File Content With Filters

15.1 Problem

How can I deploy a different content for a file than the content that was delivered by the development/build process?

Examples are:

  • Set property values of a deployed properties-file (e.g., <IS_HOME>/webadapter/webadapter.properties).
  • Manipulate XML files (e.g., <IS_SHARE>/system/config/cluster/configuration.xml).
  • Replace placeholders (e.g., '@IS.HOME@' inside shell/batch scripts).

15.2 Solution

Use configuration framework if possible

Modifying file contents through filters is a low-level operation. Please check the Recipe: Configure Intershop 7 on whether a higher level and easier approach is available first.

For example most properties-files like <IS_SHARE>/system/config/cluster/appserver.properties or orm.properties are read by the configuration framework. To override their values rather provide a <IS_SHARE>/system/config/cluster/<environment>.properties file as described in the above recipe.

Declare a content filter. You must specify:

  1. A content filter type.
  2. A unique name for the filter.
  3. A set of deployed files to apply it to, by declaring a directory, includes and excludes.
  4. Additional parameters depending on the filter type (like which properties to override with which values, how to manipulate the XML structure etc).

15.3 Discussion

This discussion initially describes everything that is independent of the filter type. After that comes a section for each built-in filter type. It is also possible to apply custom content filters, see Recipe - Apply a Custom Content Filter.

15.3.1 General Skeleton


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The general skeleton for filters looks like this:

Skeleton of filter
deployment {
	...
	filters {
		<type dependent creation method>('<name>') {
			dir = <Java File object>
			include '<Ant style pattern>'
			exclude '<Ant style pattern>'
			...
		} 
	}
}

You may define an arbitrary number of includes and excludes. Includes and excludes can be provided by:

  • Ant style patterns to match files path relative to the directory dir,
  • A closure passed in a Java File object and returning true or false (the represented file may not exist yet, for initial deployments).

A file is affected by a filter if:

  • It is located in the directory dir and
  • It is matched by at least one include (if any include is given) and
  • It is matched by no exclude.

The following example applies a filter to all pagelet-files inside <IS_SHARE>/sites or any nested directory, except for files ending in a digit:

Example of includes/excludes
deployment {
	...
	filters {
		<type dependent creation method>('<name>') {
			dir = target.shareDirectory
			include 'sites/**/*.pagelet'
			exclude { file ->
				file.path.matches /\d$/
			}
			...	
		}
	}
}

Things to keep in mind

Filters are applied based on the destination of a deployed file. It does not matter where the file was deployed from. This is especially useful, if you replace a deployed file by a different one, as done in custom fixes or patches. For example a patched shell/batch script will still have the placeholders in it replaced during deployment.

Multiple filters may be applied to the same file. The content is passed through them in a chain. The order in this chain is undetermined and should not influence the outcome.

Filters will have no effect on files that are matched by dir, include and exclude, but are not created by the deployment.

15.3.2 OverridePropertiesFilter

Use an OverridePropertiesFilter to specify property values in in properties-files. If the property exists, the filter overwrites its value, otherwise creates a new entry.

Create the filter using the method overrideProperties. Fill the map properties with all properties you want to create over overwrite.

The following example overwrites two values in <IS_HOME>/webadapter/webadapter.properties.

Example of OverridePropertiesFilter
deployment {
	...
	filters {
		overrideProperties('customizePageCache') {
       		dir = target.localDirectory
            include 'webadapter/webadapter.properties'
            properties['errorlog.level'] = 'INFO'
			properties['webadapterAgent.pageCache.expiredFiles.deletionDelay'] = 60
		}
	}
}

15.3.3 XmlContentFilter

Use an XmlContentFilter to modify xml-files. Create the filter using the method xmlContent. Specify how to modify the content by passing a closure to the method withXml. The filter passes in an XmlProvider to the closure, which can be used to read and modify the files contents.

For details on XmlProvider see Gradle API (1.8, 2.1, 2.3, 2.7, 2.11).

The following example adds a set element in <IS_SHARE>/system/config/cluster/configuration.xml after the last set element with a scope attribute of "domain". This snippet is useful for adding your own configuration sources to the configuration framework.

 

Example of XmlContentFilter
deployment {
	...
	filters {
		xmlContent('addPropertiesFileToConfigurationFramework') {
       		dir = target.shareDirectory
            include 'system/config/cluster/configuration.xml'
			withXml { XmlProvider provider ->
				def sets = provider.asNode().sets.first().children()
				def lastDomainSpecificSet = sets.findAll {it.@scope=='domain'}.last()
				def newSet = new Node(null, 'set', [finder:'property', scope:'cluster,server,domain', fileName:'/etc/config/intershop7.properties'])
				sets.add(sets.indexOf(lastDomainSpecificSet)+1, newSet)
			}
		}
	}
}

15.3.4 PlaceholderReplacementFilter

Use a PlaceholderReplacementFilter if a file contains placeholders that need to be filled by the deployment. The filter will treat all substrings of the file that start and end with specific tokens as a placeholder and take the string in between for its name. (Placeholders never span across lines.)

Create the filter using the method replacePlaceholders. Fill the map placeholders with all placeholders you want to provide values for. Optionally specify the start and end token in the properties beginToken and endToken, defaults are '<@' and '@>'.

The following example replaces all occurences of '<@IS.HOME@>' and '<@IS.SHARE@>' by their location in all shell scripts inside <IS_HOME>/bin.

Example of PlaceholderReplacementFilter
deployment {
	...
	filters {
		replacePlaceholders('placeholders') {
        	dir = target.localDirectory
			include 'bin/*.sh'
			placeholders['IS.HOME'] = target.localDirectory
			placeholders['IS.SHARE'] = target.shareDirectory
		}
	}
}

15.3.5 EditLinesFilter

Use an EditLinesFilter to modify files on a line-by-line basis. Create the filter using the method editLines. Specify how to modify the content by passing a closure to the method action. The filter calls the closure for each line of the file passing in the line as a String. Yield the modified line as return value of your closure.

The following example sets the ServerAdmin directive in the file <IS_HOME>/httpd/conf/httpd.conf.

Example of EditLinesFilter
deployment {
	...
	filters {
		editLines('provideAdminEmail') {
        	dir = target.localDirectory
			include 'httpd/conf/httpd.conf'
			action { String line ->
				line =~ /^\w*ServerAdmin/ ? 'ServerAdmin admin@customer.com' : line
			}
		}
	}
}

15.3.6 FullContentFilter

(Available since Gradle tools version 1.1)

Use a FullContentFilter to gain full access to a files content and modify it arbitrarily. Use it only for text files and files that have reasonable sizes, since the full file content will be loaded into memory at once.

Create the filter using the method fullContent. Specify how to modify the content by passing a closure to the method action. The filter calls the closure passing in a StringBuilder. Modify the content by calling methods of this StringBuilder inside the closure.

The following example appends an Include-directive to the file <IS_HOME>/httpd/conf/httpd.conf.

Example of FullContentFilter
deployment {
    ...
    filters {
        fullContent ('appendHTTPDConfInclude') {
            dir = target.localDirectory
            include 'httpd/conf/httpd.conf'
            action { StringBuilder content ->
                /*
                 * append:
                 * # MyModule configuration
                 * Include ${target.localDirectory}/etc/httpd/extra/my-module.conf
                 */
                content.append(System.lineSeparator + '# MyModule configuration' + System.lineSeparator + "Include ${target.localDirectory}/etc/httpd/extra/my-module.conf")
            }
        }
    }
}


16 Recipe: Deploy Custom Files

16.1 Problem

How to deploy files not covered by the default deployment routines?

16.2 Solution

For the deployment of files you have to configure a Gradle CopySpecsee Gradle API (2.11, 2.72.32.11.8); also see the corresponding Gradle user guide on Working With Files (2.112.72.32.11.8). You may use this to copy a single file, multiple files or extract files from an archive.

Doing this through the deployment, instead of using simple copy commands, will give you all the advantages of our indexed deployment, e.g., collision detection, modification handling and automatic undeployment.

16.3 Discussion


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

16.3.1 Artifacts

To deploy files from your source project, those files must be published to the binary repository as standalone Ivy artifact or included in a *.zip file. For further details refer to Cookbook - Gradle Build Tools.

You can then refer to the repository's artifacts in your deployment logic.

Deploy Custom Artifacts
deployment {
	files {
		example {
			// Unzip source artifact 'foo'
			from artifacts(type:'foo', extract: true)

			// Select subset to be deployed here
			include '**/*.properties'

			// Define target of the copy operation
			into new File(target.shareDirectory, 'system/config/cluster/')
		}
	}
}

16.3.2 Plain Files

You can also deploy files directly from the local file system.

Deploy Custom Files
deployment {
	files {
		productionProperties {
			// Copy a single file from the same folder as this settings.gradle file
			from new File(settingsDir, 'production.properties')
         
			// Define target of the copy operation
			into new File(target.shareDirectory, 'system/config/cluster/')
		}
	}
}

17 Recipe: Apply a Custom Content Filter

17.1 Problem

I have an artifact in which I need to replace some parts according to the environment. The predefined filters do not fit for my scenario.

17.2 Solution

To solve this problems execute the following steps:

  1. Implement your own filter.
  2. Register your filter.
  3. Configure your filter.

17.3 Discussion

17.3.1 Implement Your Own Filter

The solution starts with implementing your own filter. The best starting point is the com.intershop.deploy.filters.AbstractDeploymentContentFilter. You only need to implement your filter logic on top of this class.

An easy example for a filter replacement is replacing all placeholders in a string with another value.

ReplaceAllFilter
package com.intershop.deploy.filters;
 
import org.gradle.api.file.ContentFilterable
 
class ReplaceAllFilter extends AbstractDeploymentContentFilter
{
    Map<String, String> placeholders = [:]
    
    ReplaceAllFilter(String name)
    {
        super(name)    
    }
 
    @Override
    public void configureNormalizedFilter(ContentFilterable filterable)
    {   
        filterable.filter { String line ->
            placeholders.each {String key, value -> 
                line = line.replace(key, value)     
            }
            
            line
        }
    }          
}

17.3.2 Register Your Filter

To register your filter, add the following line to your deploy.gradle script. 

deploy.gradle
import com.intershop.deploy.filters.ReplaceAllFilter
 
deployment {
    filters {
        registerBinding(ReplaceAllFilter, ReplaceAllFilter)
    }
} 

17.3.3 Configure Your Filter 

To configure your filter, add the following lines to your deploy.gradle script.

The configuration varies according to your filter.

deploy.gradle
import com.intershop.deploy.filters.ReplaceAllFilter
 
deployment {
    filters {
        registerBinding(ReplaceAllFilter, ReplaceAllFilter)
        
        replaceAll(ReplaceAllFilter) {
           dir = infrastructureDeployment.localDirectory
           
           include 'httpd/conf/httpd.conf'
           placeholders['ServerAdmin admin@localhost'] = 'ServerAdmin admin@intershop.com'
       }
    }
}

18 Recipe: Customize the Deployment of an Archive

18.1 Problem

I need to customize the deployment of an archive. This includes renaming of files, exclusion of files or deployment of some files to another target directory.

18.2 Solution

Use a FileDeployment, which is a Gradle CopySpec for configuring the deployment.

18.3 Discussion


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The following example shows how to configure the deployment. 

It deploys the init.d files by changing the name to the directory etc/init.d.

Rename Directory During Deployment
deployment {
    files {
        initd {
            from artifacts(type:'local', extract: true)
 
            // Include files in this processing         
            include 'etc/init.d/eserverx*'
 
            // Rename files                       
            rename { String fileName ->
                fileName.replace('eserverx', "eserver${project.instanceId}")
            }
 
            // Change target directory
            into new File(infrastructureDeployment.localDirectory, 'etc/init.d')
        }
    }
}

19 Recipe: Customize Directory Handling

19.1 Problem

I need to create a directory during deployment.

19.2 Solution

Parent directories are created automatically when deploying files. There is no need for any action in this case.

To create a directory without deploying files inside,

  1. Configure a directory deployment in the deploy.gradle script of your component.

19.3 Discussion

19.3.1 Deployment


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The following example shows a sample configuration.

Create directories
deployment {
	directories {
		if (target.includeLocal) {
			localLog {
				path new File(target.localDirectory, 'log')
			}
		}

		if (target.includeShare) {
			shareLog {
				path new File(target.shareDirectory, 'system/log')
			}
		}
    }
}

This will create the directories IS_HOME/log and IS_SHARE/system/log regardless of whether or not files will be deployed into these directories.

19.3.2 Undeployment

A directory, that has not been defined as directory resource, will get deleted once its last entry is removed.

However, for directories that are defined as directory resource, the following applies:

  • Once the directory resource gets removed, all files that are not desired, will get deleted recursively. If the directory is empty afterwards, it is deleted as well.
  • The directory will not get deleted when the last entry inside gets removed (unless the directory resource itself gets removed as well).
  • The directory will not get deleted, if the directory resource gets removed, but there are still desired files inside this directory.

20 Recipe: Create a Custom Symbolic Link

20.1 Problem

I want to create a custom symbolic link at my target system.

20.2 Solution

Configure the deploy.gradle script of your component to create the link. Links are currently only supported at linux platform.

20.3 Discussion

For the creation of the link define:

AttributeDescription
fromthe location of the link
tothe target the symbolic link points to


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The following example shows a sample configuration.

Create a Symbolic Link
deployment {
    links {
        varPublic {
            from = new File(project.instanceVarDir, 'webadapter/public')
            to = new File(target.localDirectory, 'webadapter/public')
        }

        varLog {
            from = new File(project.instanceVarDir, 'log/webadapter')
            to = new File(target.localDirectory, 'webadapter/log')
        }
 
        etcDir {
            from = new File(project.instanceEtcDir, 'webadapter.properties')
            to = new File(target.localDirectory, 'webadapter/webadapter.properties')
        }
    }
}

21 Recipe: Create a Custom Service

21.1 Problem

I want to add a custom service.

21.2 Solution

 For creating a service do the following:

  1. for Windows systems
    1. Create the service executable (not scope of this document).
    2. Configure the service.
  2. for Linux systems
    1. Create the service shell script (not scope of this document).
    2. Create the init.d shell script (not scope of this document).
    3. Configure the service.

21.3 Discussion

The creation of services differs for Linux and Windows systems. By that reason you need to decide, for which platform you want to create a service. If you need to support both platforms, you need to add two configurations to your deployment script.

21.3.1 Linux Service

To configure a service for Linux you need to set the following attributes at your service definition.

AttributeDescription

serviceScript

init.d script of the service

runLevels

Run levels for the service (keep empty for no runlevel)


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The following example shows, how to configure a service for Linux.

Create a Linux Service
deployment {
    services {
        linux {
 	        webAdapter {
                serviceScript = new File(target.localDirectory, "etc/init.d/eserver${target.instanceId}-httpd")
                runLevels = [3,5]
            }
        }
    }
}

21.3.2 Windows Service

To configure a service for Windows you need to set the following attributes at your service definition. 

AttributeDescription
serviceNameName of your service (ID)
commandCommand to execute the service
displayNameName of the service which is displayed to the user
startupType

Type of startup configuration

  • com.intershop.deploy.resources.WindowsServiceDeployment.StartupType.AUTOMATIC
  • com.intershop.deploy.resources.WindowsServiceDeployment.StartupType.ENABLED
  • com.intershop.deploy.resources.WindowsServiceDeployment.StartupType.DISABLED 
userUser the service should be executed with

The following example shows, how to configure a service for Windows.

Create a Windows Service
deployment {
    services {
        windows {
	        webAdapter {
		        serviceName = 'Service 1'
                command = [
                    new File(target.localDirectory, 'httpd/bin/httpd.exe').absolutePath,
                    '-k', 'runservice',
                    '-n', serviceName,
                    '-f', new File(target.localDirectory, 'httpd/conf/httpd.conf').absolutePath]
                displayName = 'INTERSHOP HTTP Server'
                startupType = com.intershop.deploy.resources.WindowsServiceDeployment.StartupType.AUTOMATIC
                user = assemblyDeployment.user
            }
        }
    }
}

Because you must be administrator to install services, the deployment will not automatically create the new service during deployment. The result of the deployment will be a postinstall script which must be executed by an administrator.

22 Recipe: Deploy a Custom Web Application

Since Gradle tools version >= 2.0.

22.1 Problem

I need to deploy an additional *.war file into the servlet container.

22.2 Solution

The Tomcat servlet container of Intershop 7 can be used to host any *.war file and is not limited to the Intershop application.

Gradle Deployment Tools 2.0 introduced a new extensible API for Tomcat server instances. You have to

  1. Make your web app available as a component.
  2. Define your extension API to configure the web app in the DSL.
  3. Add the deployment logic to your component's deploy.gradle script.
  4. Use your newly defined extension API in the deployment's settings.gradle script.
  5. (Optional) Add a new host type for your web app (including tcm, 3rd_tomcat and runtime), see Cookbook - Gradle Assembly Tools or Cookbook - Gradle Assembly Tools (valid to 7.8), depending on your version. 

22.3 Discussion


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

22.3.1 Configuration DSL

The following snippet shows the structure of the Tomcat DSL.

Tomcat server instance configuration
tomcat {
	instances {
		instanceName {
			// insert server-specific configuration here
		}
    }
}

Specify a given tomcat instance to host your custom web app. For this purpose each Tomcat instance object is ExtensionAware, see Gradle API (2.11, 2.72.32.12.0) and can be customized via extensions. There are several possibilities to leverage this functionality:

22.3.1.1 No Additional Configuration Needed

In cases where your custom web app does not need custom configuration, you can just attach a named flag to the Tomcat instance:

Custom flag
ext.myExt = true

This code will create an additional flag named myExt, that just marks the Tomcat instance for your deployment script.

22.3.1.2 Custom Extension Class

When you need additional configuration properties for your web app, it is recommended to use a JavaBean-compliant class for your extension:

Custom extension object
extensions.create('myExt', MyExtClass)
myExt {
	foo = 'bar'
}

This code will create an extension named myExt with a new instance of class MyExtClass. Then you can configure your extension the usual Gradle-way.

22.3.1.3 Dynamic Extension Object

In case you want to avoid creating your own extension class, you can also use a dynamic Groovy object instead:

Dynamic extension object
extensions.add('myExt', new Expando())
myExt {
	foo = 'bar'
}

This code will create an extension named myExt with a new dynamic Groovy Expando, that you can assign any kind of properties. You can also configure this extension the usual Gradle-way.

22.3.2 Deployment Logic

Alter your component's deployment script to deploy its web app into those servers, that have been configured accordingly:

deploy.gradle
apply plugin: com.intershop.deploy.assembly.TargetPlugin
apply plugin: com.intershop.deploy.intershop.TomcatPlugin

deployment {
    if (target.includeLocal) {
        files {
    		tomcat.instances.find {
	    		it.hasProperty('myExt')
		    }.each { instance ->
			    "${instance.name}Tomcat" {
                    from artifacts(type:'webapp', extract: true)
                    into instance.baseDir
                }
		    }
        }
    }
}

The instance's baseDir refers to the specific Tomcat CATALINA_BASE directory.

23 Recipe: Replace a File Deployed by Another Component

23.1 Problem

How to replace an file which was deployed by another component?

The typical use case for this is providing a patch for a component.

Replacing a file is a drastic measure. Consider using content filters to alter an existing file instead of providing your own version, because it eases future migrations.

23.2 Solution

Use the configuration framework/deployment filters if possible

Replacing a whole file is a low-level and very drastic operation. Please check the Recipe: Configure Intershop 7 on whether a higher level and easier approach is available first.

For example most properties-files like <IS_SHARE>/system/config/cluster/appserver.properties or orm.properties are read by the configuration framework. To override their values rather provide a <IS_SHARE>/system/config/cluster/<environment>.properties file as described in the above recipe.

To solve this problem execute the following steps:

  1. Deploy a custom file to the same location as the file you want to replace.
    See the Recipe: Deploy Custom Files.
  2. Run the deployment.
    It will abort with an conflict error, because the file from the original component and your custom file will cause a conflict.
  3. Resolve the conflict by excluding the file from the deployment of the original component.

23.3 Discussion

If you configured the deployment of your custom file correctly, the deployment will abort with a DuplicateResourceException like this:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':<component 1>:deploy<deployment name 1>Files'.
> Task :<component 1>:deploy<deployment name 1>Files: Resource '<file>' already defined for Task :<component 2>:deploy<deployment name 2>Files

One of the task names belongs to your component and your FileDeployment declaration. (For the assembly the name of the component will be missing.) Fill in the other component and deployment name.

FileDeployment implements a standard Gradle CopySpec, see Gradle API (2.11, 2.72.32.11.8). To exclude the original add the following deployment configuration:


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

Order of evaluation

Since the code below configures one project from the script of another/the root project/the settings.gradle, the order of evaluation of the scripts must be considered. Please see the Recipe: Provide Custom Deployment Configuration and Logic for more detailed information on how to do this.

Exclude from the original component
if (rootProject.findProject(':<component>')) {
    rootProject.project(':<component>') {
        afterEvaluate {
            deployment.files.<deployment name> {
            	exclude { 
                	new File(destinationDir, it.path) == <file object pointing to the deployed file>)                        
                }
            }
        }
    }
}

23.3.1 Full Example

The following example shows how to replace the <IS_SHARE>/system/config/oracle/tnsnames.ora file deployed by component core.

  1. Deploy a custom version:

    Deploy custom tnsnames.ora
    deployment {
        files {
            tnsNamesOra {
                // Copy a tnsnames.ora file from the same folder as this settings.gradle file
                from new File(settingsDir, 'tnsnames.ora')             
                // Define target of the copy operation
                into new File(target.shareDirectory, 'system/config/oracle/')         
            }
        }
    }
  2. The conflict message shown during deployment: 

    Conflict Message
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':core:deployShareFiles'.
    > Task :core:deployShareFiles: Resource '...\system\config\oracle\tnsnames.ora' already defined for Task :deployTnsNamesOraFiles
  3. Exclude original file:

    • Since Gradle Tools 2.0:

      Exclude original file
      project(':core') {
      	afterEvaluate {
          	deployment.files.share {
              	exclude { 
                  	new File(destinationDir, it.path) == new File(target.shareDirectory, 'system/config/oracle/tnsnames.ora')                        
                  }
              }                                    
          }
      }
    • For Gradle Tools 1.0 and 1.1:

      Exclude original file
      if (findProject(':core')) {
          project(':core') {
              def configClosure = {
                  deployment.files.share {
                      exclude {
                          new File(destinationDir, it.path) == new File(target.shareDirectory, 'system/config/oracle/tnsnames.ora')
                      }
                  }
              }
              if (project.state.executed) {
                  configClosure()
              } else {
                  afterEvaluate(configClosure)
              }
          }
      }

24 Recipe: Keep Local Modifications

24.1 Problem

I want to customize the strategy, how the deployment proceeds when it detects external modifications on deployed resources.

24.2 Solution

Modification handling can be configured on two levels:

  • It can be configured on a per-file basis via an includes/excludes-based DSL.
  • Files not covered by any specific modification handling specification are handled according to a global default strategy.

24.3 Discussion

Regardless of the way of configuration, there are four modification handling strategies available:

Strategy nameBehaviour
overwritealways overwrites local modifications and causes a warning
keepalways keeps local modifications, thereby skips deployment of this resource, and causes a warning
abortaborts the deployment process in case of a conflict without altering locally modified resources
backup

renames the existing file by appending -backup or -backup1, -backup2 etc to avoid conflicts

You must assign a priority to each modification handling specification. A priority is just a string and its rank is defined by a list, that names all available priorities in ascending order. Please, consider the priorities ['default', 'intershop'], in which case intershop has a higher priority than default. These priorities allow for fine-grained control over which modification handling strategy is to be used for any given file. There are two priorities defined per default:

  • default is the priority of the global fallback strategy, see below
  • intershop is the priority of all file-specific modification handling specifications, that are predefined in standard IS7.

Customer projects are encouraged to use an own priority level, to be able to override both default and intershop specifications.

Avoid Conflicts!

Modification handling specifications must not be ambiguous! If two handlers apply to the same file, they must differ in their priority levels, in which case the higher priority specification wins.

24.3.1 Global Configuration


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

The global fallback modification handling strategy is configured as a property in the deployment DSL, as is the order of handling priorities:

Global Configuration for Modification Handling
assemblyDeployment {
	//...
	defaultModificationHandler = 'abort'
	modificationPriorities = ['default', 'intershop', 'myProject']		
}

24.3.2 Configure Handling of Specific Resources

Components can declare how their deployed components are to be handled in case of an external modification. Modification specification via includes/excludes works just like it does for filters:

Handling of Specific Resources
deployment {
	modification {
		backup('intershopProperties') {
			priority 'myProject'
			dir target.localDirectory
			include 'intershop.properties'
		}
	}
}

25 Recipe: Deploy Data Replication Environment

25.1 Problem

I want to deploy systems that participate in a data replication environment.

25.2 Solution

Setting up a simple two-node data replication environment involves the following major tasks:

25.3 Discussion

The data replication deployment involves at least one source cluster and one target cluster. The number of IAS and IWS instances and their distribution is irrelevant to the data replication mechanism. This recipe illustrates a simple two-node data replication deployment, which includes two single-host Intershop 7 clusters (using the host type all).

The following sections assume that the deployment preconditions (as described in Recipe: Prepare the Deployment) are met, i.e., that the Intershop 7 users, the deployment target directories etc are prepared on both nodes.

25.3.1 Deploying the Target Cluster

When setting up a data replication environment, you must first deploy the target (live) cluster in order to get a replication configuration file, which must be copied and modified for deploying the source (editing) cluster later.

To deploy the target cluster, follow the proceedings as described in Recipe: Configure the Deployment. The config DSL block of the settings.gradle file, however, needs some additional information:

  • an individual live database user
  • a staging type setting
config {
  ...
  database {
    host = '<db-hostname>'
    port = <db-port>
    serviceName = '<db-servicename>'
    tnsAlias = '<db-tnsalias>'
    user = '<live-db-user>'
    password = '<live-db-password>'
    oracleClientDir = new File('</opt/oracle/client|c:/oracle/client>')
  }
  staging {
    systemType = 'live'
  }
}

For more details, see Recipe: Configure Mass Data Replication.

25.3.2 Modifying the Data Replication Configuration

The source (editing) cluster needs a specific data replication configuration, which tells it the required details of the target (live) cluster. To prepare the source cluster configuration:

  1. Copy the example replication configuration file to the deployment directory of the source (editing) cluster host.
    This file, replication-clusters.xml.sample, is located in /opt/intershop/eserver1/share/system/config/cluster of the deployed target (live) cluster.

  2. Open the copied replication configuration file and edit the settings as required.
    The following parameters must be set:

    ParameterDescription/Example

    Target system, ID and activity

    <target-system id="TargetSystem" active="true">
    Web server URL<webserver-url>http://target(live)-system-host:port</webserver-url>

    Database source/target communication

    Use either a database link or, if the source and target system databases reside in the same database instance, a direct schema access.

    Database link: <source-database-link>ISEDITING</source-database-link>

    Target schema name for direct schema access: <target-database-user>INTERSHOP_LIVE</target-database-user>

25.3.3 Deploying the Source Cluster

To deploy the source cluster, follow the proceedings as described in Recipe: Configure the Deployment. As with the deployment of the target cluster, the config DSL block of the settings.gradle file needs additional information:

  • an individual editing database user
  • a staging type setting and the specific data replication configuration.
config {
  ...
  database {
  host = '<db-hostname>'
  port = <db-port>
  serviceName = '<db-servicename>'
  tnsAlias = '<db-tnsalias>'
  user = '<edit-db-user>'
  password = '<edit-db-password>'
  oracleClientDir = new File('</opt/oracle/client|c:/oracle/client>')
  }
  staging {
    systemType = 'editing'
    replicationClustersFile = new File('</opt/intershop/install/replication-clusters.xml|c:/install/replication-clusters.xml>')
  }
}

25.3.4 Data Replication Post Configuration

Preparing data replication environments involves additional post-deployment tasks:

  • Checking Replication Configuration Files
  • Initializing the Database for Replication
  • Creating a Database Link

25.3.4.1 Checking Replication Configuration Files

Intershop recommends to recheck the configuration files for the data replication after the clusters' deployment. In both the target cluster and the source cluster, the corresponding files staging.properties and replication-clusters.xml are located in <eserver#>/share/system/config/cluster.

Make sure that the following details are properly set:

staging.properties

Provides basic settings like the system role (editing, live) for the current Intershop 7 cluster, must be configured in both clusters (source and target).

In the source cluster, the staging type setting must be

staging.system.type = editing

In the target cluster, the staging type setting must be

staging.system.type = live

replication-clusters.xml

Provides the communication setting for a source cluster to connect to the target cluster(s) via database link or database schema access, must be configured in the source cluster.

When using a database link between two database instances, the target-system section must include a line like

<source-database-link>ISEDITING</source-database-link>

When directly accessing a database schema within one database instance, the target-system section must include a line like

<target-database-user>INTERSHOP_LIVE</target-database-user>

25.3.4.2 Initializing the Database for Replication

The data replication mechanism is based on a set of specific tables (live and shadow tables), which need to be created before the actual data replication can take place. This requires to initialize the database accordingly. Two basic approaches are available to initialize the database in a new replication environment:

  • Running a DBinit process on the source (editing) cluster, then exporting a database dump and importing this dump in the target (live) cluster
    With this approach, you can already prepare the required database tables when executing the DBinit process. For information about DBinit, refer to Cookbook - DBInit

  • Importing an existing database dump in both the source (editing) and the target (live) clusters
    With this approach, the database tables required for the data replication are created during the first replication process. For information about data replication, the involved procedures, its initialization etc, refer to Cookbook - Mass Data Replication - Administration.

A database link is a probable option to provide for the communication between the source cluster and the target cluster. If you chose to use a database link, you must create it in the database schema of the target cluster. To do so, log on to the target cluster as the live database user <live-db-user> and issue the following SQL commands (replacing the placeholders).

To remove an old database link, execute

DROP DATABASE LINK isediting;

To create a new database link using, for example, the easy connect syntax, execute

CREATE DATABASE LINK isediting CONNECT TO <edit-db-user>
  IDENTIFIED BY <edit-db-password>
  USING '//<edit-db-hostname>:<edit-db-port>/<service_name>';

To test the database link, execute

SELECT tname FROM tab@isediting;

26 Recipe: Undeploy

26.1 Problem

How to undeploy the whole assembly?

26.2 Solution

There is a dedicated Gradle task to undeploy all artifacts of the installed assembly. This task undeploys all artifacts, that have been registered in the index file during previous deployment operations. The handling of artifacts, that have not been indexed, can be configured.

Undeployment during upgrade

Installing a new assembly (version) automatically removes obsolete files from previous deployments.

26.3 Discussion

26.3.1 Execute Undeployment

To start the undeployment:

  1. Execute the following command as the user, who originally deployed the assembly.

    <gradle command> undeploy

Note

Running Services

You cannot remove the server's artifacts, as long as its services are still running. In this case proceed as follows:

  1. Undeploy the services.

    <gradle command> undeployServices
  2. Stop and remove services using the generated Post-Install script.
  3. Undeploy the rest of the assembly.

    <gradle command> undeploy

26.3.2 Configure Cleanup

Additional files are placed into the installation directories by the running server, e.g., log files or page compile artifacts. As those files are not registered in the index, undeployment cannot associate those files with installed components.

You can configure whether or not those artifacts are to be deleted in your local installation's settings file:


Use Code Examples

The code examples provided in this recipe can be copied to the deploymentBootstrap.config block of the settings.gradle at deployment time.

settings.gradle
...
deploymentBootstrap {
	...
	config {
		// Insert code examples here
	}
}

During development you can create a deploy.gradle, which will be used automatically.

<cartridge>/deployment/deploy.gradle
// Insert code examples here

See Recipe: Provide Custom Deployment Configuration and Logic for additional places (like assemblies).

Configure Cleanup
//...
assemblyDeployment {
	//... 
	purgeUnknownFiles = false    
}

Setting this value to true will cause the undeployment process to delete all files inside known directories (such as local or share).

27 Recipe: Deploy a Local Eureka Server

27.1 Problem

I want to deploy a local Eureka server and want to use it for service discovery.

27.2 Solution

27.2.1 Example

settings.gradle
config {
	...
	eureka {
		serverHostName = 'localhost'
    	serverPort = 'my_port'
    	serverUrlPath = 'eureka/'
    	serverReplicaUrl = 'replica_url'
		serverEnvironment = 'LIVE'
		// service url is mandatory for clients instances (appserver, solr, microservices, etc.), but not within the settings.gradle for the host type serviceDiscovery it's not necessary
		// serviceUrls.default = 'http://<host_name>:<my_port>/eureka/'
  	}
}

 

Following attributes can be configured within a Eureka extension:

AttributeMandatoryDescription
serverHostNameyesThe host name or IP where Eureka is deployed
serverPortyesThe port at which Eureka is operating on
serverUrlPathyes

The server URL suffix (in most cases eureka 'eureka/')

Note

Ensure to use the trailing slash '/' at the end. Otherwise the service discovery will not work properly.

serverReplicaUrlnoEureka server replicas may be configured here.
serverEnvironmentnoA property, which is shown in the Eureka UI

serviceUrls

see info field

The URL, which Eureka clients use to register at Eureka server.

The URL must be composed from the serverHostName, serverPort and serverUrlPath to use the locally deployed eureka (http://<serverHostName>:<serverPort>/<serverUrlPath>)

serviceUrls

 It is mandatory for the settings.gradle of the instance, where the application server, the Solr server or the microservices will be deployed. See: Recipe: Register ICM at Eureka or Recipe: Microservice Deployment.

Note

Ensure to use the trailing slash '/' at the end. Otherwise the service discovery will not work properly.

27.3 Discussion

The serviceUrls attribute provides the possibility to choose at which server the clients should be registered. This means, another Eureka server can be chosen to register clients.

27.3.1 Resiliency

For a software system using service discovery, both the clients and the servers need to be resilient.

  • Eureka clients are built to handle the failure of one or more Eureka servers. Since Eureka clients have the registry cache information in them, they can operate reasonably well, even if all of the Eureka servers go down.
  • Eureka servers are resilient to other Eureka peers going down. Even during a network partition between the clients and servers, the servers have built-in resiliency to prevent a large scale outage.

Further information can be found here: Eureka Wiki

28 Recipe: Register ICM at Eureka

This recipe is only valid for the additional Solr Cloud assembly for Intershop 7.9. If this assembly isn't used the original recipe from 7.8 remains valid.

28.1 Problem

I want to register the ICM application server, the SolR server and the Web Adapter agent at the Eureka server.

28.2 Precondition

You need to have access to an Eureka server: You can accomplish this by:

28.3 Solution

It is necessary to configure the extensions within the settings.gradle file for the according host types before deploying the server. For details, see: Recipe: Configure the Deployment.

28.3.1 Host Type: share

settings.gradle - appServer
config {
	appserver{
		serviceAppName = 'appServerName'    
	}
	eureka {        
        serviceUrls.default = 'http://<host_name>:<my_port>/eureka/'
   	}
	microservices {
        configProperties['intershop.naming.service.RecurringOrder'] = 'microserviceName'
        configProperties['intershop.naming.service.Scheduling'] = 'microserviceName'
   }
} 

 

28.3.2 Host Type: webserver

settings.gradle -SolRServer
config {
	appserver{
		serviceAppName = 'appServerName'    
	}
	eureka {        
        serviceUrls.default = 'http://<host_name>:<my_port>/eureka/'
   	}
 } 

serviceAppName

These values must not contain an underline ("_") For further see (RFC-1034 – Section 3.5)
AttributesUsed within extensionUsed in host type: shareUsed in host type: webserverDescription
serviceAppName

appserver

yesyesThe name under which the application server is registered at the Eureka server
serviceUrls.default

eureka

yesyesThe Eureka URL, which is used to register at Eureka
See: Recipe: Deploy a Local Eureka Server or the registration URL of a global Eureka server

29 Recipe: Microservice Deployment

29.1 Problem

I want to deploy the microservices.

29.2 Precondition

It is is necessary to have access to an Eureka server: You can accomplish this by the fulfillment of:

29.3 Solution

It is necessary to configure the extensions in the settings.gradle file for the host type 'microservices' before deploying the server. For details, see Recipe: Configure the Deployment.

settings.gradle
config {
	microservices {
		port = '<MY_PORT>' 
		name = 'microserviceName'
		instanceId= 'microserviceInstanceId'
            
		configProperties['javax.persistence.jdbc.url']  = '<CONNECTION_URL_DATABASE>'
		configProperties['javax.persistence.jdbc.user']  = '<DATABASE_USER>'
		configProperties['javax.persistence.jdbc.password']  = '<DATABASE_PASSWORD>'
            
		configProperties['intershop.naming.service.RecurringOrder'] = 'microserviceName'
		configProperties['intershop.naming.service.Scheduling'] = 'microserviceName'
 	}
	appserver{
        serviceAppName = 'appServerName'   
    }
    eureka {        
        serviceUrls.default = 'http://<host_name>:<my_port>/eureka/'
    }

 }
AttributeExtensionDescription
port

microservices

The port on which the microservices are operating
name

microservices

The name, which the microservices are using to register at Eureka server
instanceId

microservices

The instance ID, Which the microservices are using to register at Eureka server
configProperties

microservices

Map of configuration for the microservices
configProperties['javax.persistence.jdbc.url']

microservices

The database connection URL
configProperties[javax.persistence.jdbc.user']

microservices

The database user
configProperties['javax.persistence.jdbc.password']

microservices

The database password
configProperties['intershop.naming.service.RecurringOrder']

microservices

The name of the Recurring Order service
configProperties['intershop.naming.service.Scheduling']

microservices

The name of the Scheduling service
serviceUrls.default

eureka

The Eureka URL, which is used to register at Eureka

See: Recipe: Deploy a Local Eureka Server or the registration URL of a global Eureka server

serviceAppName

appserver

The name the application server is registered at the Eureka server

See Recipe: Register ICM at Eureka for details

name

The value of the attribute name  must not contain an underline ("_") For further see (RFC-1034 – Section 3.5)

For naming restrictions of the name of the microservices, the scheduling and the recurring order service, please see the discussion

29.4 Discussion

The configProperties attribute allows to add further properties, which can be set during deployment without the need to adapt the microservice extension.

There is another JDBC property: javax.persistence.jdbc.driver which is listed within the environment.properties of the microservices. This property was separated from the other JDBC properties, since it does not belong to the configuration.

29.4.1 Deploy the Recurring Order Service and the Scheduling Service Together

The names of microservice, the Recurring Order service and the Scheduling service must be the same (name = 'microserviceName').

settings.gradle
config {
	...
	microservices {
		...
		name = 'microserviceName'
		...
            
		configProperties['intershop.naming.service.RecurringOrder'] = name 
		configProperties['intershop.naming.service.Scheduling'] = name
	}
}

29.4.2 Deploy the Recurring Order Service and the Scheduling Service Separately

Assume you have two instances <Instance_1> and <Instance_2>.

  • The Recurring Order service should be installed on <Instance_1>
  • The Scheduling service should be installed on <Instance_2>

The service name (configProperties['intershop.naming.service.RecurringOrder'] = 'recurringOrder'), that should be deployed on this instance, has to match to the name (name = 'recurringOrder'), which is used to register at Eureka server. The service name of the other service, which is deployed on the other instance, has to match to the name used by the other instance. So the settings.gradle files for the instances have to be configured the following way

settings.gradle <Instance_1>
config {
	microservices {
		name = 'recurringOrder'
            
		configProperties['intershop.naming.service.RecurringOrder'] = 'recurringOrder'
		configProperties['intershop.naming.service.Scheduling'] = 'scheduling'
	}
}
settings.gradle <Instance_2>
config {
	microservices {
		name = 'scheduling'
            
		configProperties['intershop.naming.service.RecurringOrder'] = 'recurringOrder'
		configProperties['intershop.naming.service.Scheduling'] = 'scheduling'
	}
}

 

30 Recipe: Setup Project Using Solr Cloud

Note

It is essential to utilize Intershop version 7.9 or later to enable the use of Solr Cloud.

30.1 Problem

I want to use Solr Cloud instead of the default Solr 4.

30.2 Solution

Therefore following steps are necessary:

30.2.1 General Adaption of the Project Assembly

  1. The general steps for the adaption of the project assembly need to be executed.
    See Recipe - Setup Project based on the Responsive Starter Store for details.

30.2.2 Utilize the Solr Cloud Components

  1. Adapt the build.gradle of the multi-project.

    build.gradle
    versionRecommendation {
        provider {
           
    +       // solrcloud dependencies provides all solr cloud related cartridges
    +       properties('solrcloud', file('solrcloud.version')) {}
    
        }
        
    }
  2. Add a file 'solrcloud.version' within the multi-project root directory.

    solrcloud.version
    com.intershop.solrcloud:*=<CURRENT_SOLR_CLOUD_VERSION>

    This notation assigns all solr cloud components the same version,

30.2.3 Adapt Compile Dependencies of the Sub-Projects

  1. If app_sf_responsive, app_sf_responsive_b2b are used, renamed or replaced the compile dependencies within their build.gradle has to be adapted.

    app_sf_responsive/build.gradle
    -    compile group: 'com.intershop.business', name: 'ac_search_solr'
    +    compile group: 'com.intershop.solrcloud', name: 'ac_solr_cloud'
    app_sf_responsive_b2b/build.gradle
    -    compile group: 'com.intershop.business', name: 'ac_search_solr'
    +    compile group: 'com.intershop.solrcloud', name: 'ac_solr_cloud'

30.2.4 Remove Old Solr 4 Cartridges

  1. The old Solr4 cartridges, which are inherited from f_business has to be excluded from the project assembly.

    project_assembly/build.gradle
     assembly {
         inheritFrom('com.intershop.assembly:commerce_management_b2x') {
    +        // Within this assembly solr cloud should be used. Therefore it's necessary to exclude all solr 4 related cartridges.
    +        excludeDependencies '3rd_solr_war_int', 'ac_search_solr', 'ac_search_solr_bo', 'ac_search_solr_test', 'ac_eureka_solr'
         }
    }

30.2.5 Remove Components from Host Type Solr

  1. Since host types are inherited from the parent assembly, they cannot be deleted. But it is possible to exclude components for a host type.
    So an empty host type solr remains within the project assembly.

    project_assembly/build.gradle
     assembly {
         hostTypes {
    +        // A host type can't be removed, but components can be excluded from a host type.
    +        // So the host type solr is empty, and no artifacts related to this host type are deployed to the 'local' directory anymore.
    +        solr {
    +            exclude group:'com.intershop', module:'3rd_tomcat'
    +            exclude group:'com.intershop.infrastructure', module:'runtime'
    +            exclude group:'com.intershop.infrastructure', module:'tcm'
    +            exclude group:'com.intershop.business', module:'3rd_solr_war_int'
    +        }
    	}
    }

30.2.6 Include Solr Cloud Cartridges and Adapt the Cartridge List

  1. Beside the inclusion of the cartridges to the project assembly an adaption of the cartridge list is necessary.
    The Solr Cloud cartridges need to be at the same position as their Solr 4 counterparts.

    project_assembly/build.gradle
     assembly {
         cartridges {
    +        def solrCloudProductionCartridges = [
    +            'ac_solr_cloud',
    +            'ac_solr_cloud_bo',
    +        ]
    +        
    +        include('com.intershop.solrcloud:ac_solr_cloud',
    +                'com.intershop.solrcloud:ac_solr_cloud_bo',
    +                            in:[development, test, production])
    +
    +        def solrCloudTestCartridges = [
    +            'ac_solr_cloud_test',
    +        ]
    +        
    +        include('com.intershop.solrcloud:ac_solr_cloud_test',
    +                            in:[development, test])
    
    -        order = listFromAssembly('com.intershop.assembly:commerce_management_b2x') + storefrontCartridges + initCartridges + developerCartridges + testCartridges
    +        
    +        // Ensure the new solr cloud cartridges are at the correct position in the cartridge list. It's important for a working dbinit! 
    +        // Insert them before ac_search_solr* sub-projects. 
    +        // The old solr4 cartridges are still part of the cartridge list at the moment, but they are removed, before the ivy is generated
    +        def commerceCartridgesCartridges = listFromAssembly('com.intershop.assembly:commerce_management_b2x')
    +        def solrCloudCartridges = commerceCartridgesCartridges.plus(commerceCartridgesCartridges.indexOf('ac_search_solr'), solrCloudProductionCartridges)
    +        solrCloudCartridges = solrCloudCartridges.plus(solrCloudCartridges.indexOf('ac_search_solr_test'), solrCloudTestCartridges)
    +        
    +        order = solrCloudCartridges+ storefrontCartridges + initCartridges + developerCartridges + testCartridges
    
    	}
    }

30.2.7 Adapt the Deployment of the Project Assembly

  1. The deploy.gradle must not be inherited from commerce_management_b2x, it must contain its own deploy.gradle file.

    project_assembly/build.gradle
    assembly {
         inheritFrom('com.intershop.assembly:commerce_management_b2x') {
    -        includeArtifacts type:['deploy-gradle', 'deploy-settings-gradle']
    +        includeArtifacts type:['deploy-settings-gradle']
    }
  2. The solrcloud* properties below needs to be defined within the deploy.gradle.
    See Recipe: Configure the Deployment - extension solr

    project_assembly/deploy.gradle
    +apply plugin: com.intershop.deploy.intershop.IntershopPlugins
    +apply plugin: com.intershop.deploy.intershop.SolrCloudDeploymentPlugin
    +
    +deployment {
    +    if (target.includeShare) {
    +        filters {
    +            overrideProperties('solrCloudProperties') {
    +                dir target.shareDirectory
    +                include 'system/config/cartridges/ac_solr_cloud.properties'
    +				properties['solr.zooKeeperHostList'] = solrcloud.zooKeeperHostList
    +                properties['solr.clusterIndexPrefix'] = solrcloud.clusterIndexPrefix
    +            }
    +        }
    +    }
    +}

Disclaimer

The information provided in the Knowledge Base may not be applicable to all systems and situations. Intershop Communications will not be liable to any party for any direct or indirect damages resulting from the use of the Customer Support section of the Intershop Corporate Web site, including, without limitation, any lost profits, business interruption, loss of programs or other data on your information handling system.

Customer Support
Knowledge Base
Product Resources
Support Tickets