“You do not really understand something unless you can explain it to your grandmother”
Albert Einstein.
This quote pushed me to start this blog. Why I'm writing the blog in English? The answer is quite simple, to improve my English :)
These articles will include two points Requirement (the issue) and Solution (how to solve the issue). So let's begin.
Requirement:
Update the jar files in Documentum repository immediately after it is created.
Solution:
We all know that for update a
documentum module TBO, SBO it is enough just to checkout - checkin the jar file
inside the module folder, yes there are a lot of mode to do that: DA, WebTop,
Composer (that usually fails), ... but the requirement is to update it
automatically in repository after it is created. I have decide to put this
procedure immediately after the jar is created, of course in Ant task.
The Ant task in build.xml will look
like that:
<!-- Update
jarfiles in docbase -->
<checkoutcheckin>
<docbaseobject
jarfile=".dist/ex_interfaces.jar"
jarobject="ex_interfaces.jar"
/>
<docbaseobject
jarfile="./dist/ex_impl.jar"
jarobject="ex_impl.jar"
/>
</checkoutcheckin>
It looks very nice
isn’t it?
First of all we need to declare Ant custom
CheckOutCheckIn class extends Task class which will do
the given job.
public
class CheckOutCheckIn extends
Task {
@Override
public
void execute() throws
BuildException {
// TODO
Auto-generated method stub
super.execute();
}
}
Yes, you have notice correctly, the execute() method
is the method which shall do the job. Our execute() method will be quite
simple:
@Override
public
void execute() throws
BuildException {
String classPath = System.getProperties().getProperty("java.class.path",
null);
log("Class
Path: " + classPath);
try
{
initSession();
doCheckout();
doCheckin();
} catch
(DfException e) {
throw
new BuildException(e);
} catch
(Exception e) {
throw
new BuildException(e);
} finally
{
releaseSession();
}
}
That’s not enough, we need a
way to map the jar files and the docbase object. For that I have create an
inner bean class which will contain a jarFile/object pair inside.
public
static class
DocBaseObject extends
Task {
private
String jarfile;
private
String jarobject;
public
DocBaseObject() {
}
public
DocBaseObject(String file, String object) {
jarfile
= file;
jarobject
= object;
}
public
String getJarfile() {
return
jarfile;
}
public
void setJarfile(String localfile) {
this.jarfile
= localfile;
}
public
String getJarobject() {
return
jarobject;
}
public
void setJarobject(String docbaseObject) {
this.jarobject
= docbaseObject;
}
}
This class also extends Ant
Task class because we will use it like inner parameter to the main Ant task. So
our class now looks like this:
public
class CheckOutCheckIn extends
Task {
@Override
public
void execute() throws
BuildException {
String classPath = System.getProperties().getProperty("java.class.path",
null);
log("Class
Path: " + classPath);
try
{
initSession();
doCheckout();
doCheckin();
} catch
(DfException e) {
throw
new BuildException(e);
} catch
(Exception e) {
throw
new BuildException(e);
} finally
{
releaseSession();
}
}
public
static class
DocBaseObject extends
Task {
private
String jarfile;
private
String jarobject;
public
DocBaseObject() {
}
public
DocBaseObject(String file, String object) {
jarfile
= file;
jarobject
= object;
}
public
String getJarfile() {
return
jarfile;
}
public
void setJarfile(String localfile) {
this.jarfile
= localfile;
}
public
String getJarobject() {
return
jarobject;
}
public
void setJarobject(String docbaseObject) {
this.jarobject
= docbaseObject;
}
}
}
It remains only to add implementation to all methods. Let’s start
with inititSession() method:
private
void initSession() throws
Exception {
URL urlPath = null;
//getting
ClassLoader for load dfc.properties
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if
(classLoader != null) {
urlPath =
classLoader.getResource("dfc.properties");
}
if
(urlPath == null) {
urlPath = CheckOutCheckIn.class.getResource("dfc.properties");
}
if
(urlPath == null) {
urlPath = CheckOutCheckIn.class.getClassLoader().getResource("dfc.properties");
}
log("dfc.properties
path:" + urlPath.getPath());
//set the dfc.properties.file
parameter
System.setProperty("dfc.properties.file",
urlPath.getPath());
//get
config.properties file for initiate user name, password and docbase name
ResourceBundle ownerBundle =
ResourceBundle.getBundle("config");
String docbaseName =
ownerBundle.getString("docbase");
String userName =
ownerBundle.getString("username");
String password =
ownerBundle.getString("password");
log("Creating
session manager docbase: " + docbaseName + "
...");
sMgr
= createSessionManager(docbaseName, userName, password);
log("Getting
session from docbase " + docbaseName + "
(might take some seconds) ...");
session
= sMgr.getSession(docbaseName);
log("Session
oppened.");
}
The files config.properties and dfc.properties should be in class path, this can be done when the Ant task is
declared in build.xml.
<taskdef
name="checkoutcheckin"
classname="com.example.ant.CheckOutCheckIn">
<classpath>
<pathelement
location="${proj.location}/config/${build.env}"
/>
<pathelement
location="${proj.location}/dist/checkoutcheckin.jar"
/>
</classpath>
</taskdef>
The parameter ${build.env}
can has the values (dev,test …) like you can see below.
The content of property file config.properties might be something like that:
docbase=DEV
username=dmadmin
password=dmadmin
The content of dfc.properties file I think is not
necessary to show. :)
I have chosen this
method to set environment because in our project there are already these
folders.
Let’s go back to class, we have to add implementation to all
methods. Next method is called doCheckout():
private
void doCheckout() throws
DfException {
log("Checkout
start ...");
IDfClientX clientx = new
DfClientX();
IDfCheckoutOperation operation =
clientx.getCheckoutOperation();
//iterate over
all <docbaseobject> inner elements from Ant task
for
(DocBaseObject docbaseObj : docbaseobjects)
{
IDfSysObject sysObj =
(IDfSysObject) session.getObjectByQualification("dmc_jar
where object_name='" + docbaseObj.getJarobject() + "'");
if
(sysObj == null) {
log("Object:
" + docbaseObj.getJarobject() + " can not be
found.");
continue;
}
if
(sysObj.isCheckedOut() == true)
{
log("Object:
" + docbaseObj.getJarobject() + " is already
checked out.");
continue;
}
operation.add(sysObj);
log("Object:
" + docbaseObj.getJarobject() + " added to
Checkout Operation.");
}
executeOperation(operation);
log("Checkout
end.");
}
private
void executeOperation(IDfOperation
operation) throws DfException {
boolean
executeFlag = operation.execute();
//if the
operation fails then log all errors
if
(!executeFlag) {
IDfList errorList =
operation.getErrors();
String message = "";
IDfOperationError error = null;
for
(int i = 0; i < errorList.getCount();
i++) {
error =
(IDfOperationError) errorList.get(i);
message +=
error.getMessage();
}
log("Errors:"
+ message);
} else
{
log("Checkout
Operation ends successful");
}
}
I choose IDfCheckoutOperation to checkout all the objects simultaneously. But for doCheckin() operation I do not
choose this way because the jar files might be in different folders. So the doCheckin() method is:
private
void doCheckin() throws
DfException {
log("Checkin
start ...");
//iterate over all
<docbaseobject> inner elements
for
(DocBaseObject docbaseObj : docbaseobjects)
{
IDfSysObject sysObj =
(IDfSysObject) session.getObjectByQualification("dmc_jar
where object_name='" + docbaseObj.getJarobject() + "'");
if
(sysObj == null) {
log("Object:
" + docbaseObj.getJarobject() + " can not be
found.");
continue;
}
if
(sysObj.isCheckedOut() == false)
{
log("Object:
" + docbaseObj.getJarobject() + " is not checked
out.");
continue;
}
sysObj.setFile(docbaseObj.getJarfile());
sysObj.checkin(false,
"CURRENT");
log("Object:
" + docbaseObj.getJarobject() + ", file: "
+ docbaseObj.getJarfile() + " checked in.");
}
log("Checkin
end.");
}
Finally the class
will be:
package com.example.ant;
import java.net.URL;
import java.util.List;
import
java.util.ResourceBundle;
import
java.util.Vector;
import
org.apache.tools.ant.BuildException;
import
org.apache.tools.ant.Task;
import
com.documentum.com.DfClientX;
import
com.documentum.com.IDfClientX;
import
com.documentum.fc.client.IDfClient;
import
com.documentum.fc.client.IDfSession;
import
com.documentum.fc.client.IDfSessionManager;
import
com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.common.DfException;
import
com.documentum.fc.common.IDfList;
import
com.documentum.fc.common.IDfLoginInfo;
import
com.documentum.operations.IDfCheckoutOperation;
import
com.documentum.operations.IDfOperation;
import com.documentum.operations.IDfOperationError;
public class CheckOutCheckIn extends Task {
private
List<DocBaseObject> docbaseobjects = new Vector<DocBaseObject>();
public static
IDfSessionManager sMgr = null;
public static IDfSession session = null;
public void
addDocbaseobject(DocBaseObject docbaseobject) {
docbaseobjects.add(docbaseobject);
}
@Override
public void execute() throws BuildException {
String
classPath = System.getProperties().getProperty("java.class.path", null);
log("Class Path:
"
+ classPath);
try {
initSession();
doCheckout();
doCheckin();
}
catch (DfException e)
{
throw new
BuildException(e);
}
catch (Exception e) {
throw new
BuildException(e);
}
finally {
releaseSession();
}
}
private void initSession() throws Exception {
URL
urlPath = null;
//getting
ClassLoader for load dfc.properties
ClassLoader
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader != null) {
urlPath
= classLoader.getResource("dfc.properties");
}
if (urlPath == null) {
urlPath
= CheckOutCheckIn.class.getResource("dfc.properties");
}
if (urlPath == null) {
urlPath
= CheckOutCheckIn.class.getClassLoader().getResource("dfc.properties");
}
log("dfc.properties
path:" + urlPath.getPath());
//set the
dfc.properties.file parameter
System.setProperty("dfc.properties.file",
urlPath.getPath());
//get
config.properties file for initiate user name, password and docbase name
ResourceBundle
ownerBundle = ResourceBundle.getBundle("config");
String
docbaseName = ownerBundle.getString("docbase");
String
userName = ownerBundle.getString("username");
String
password = ownerBundle.getString("password");
log("Creating
session manager docbase: " + docbaseName + " ...");
sMgr =
createSessionManager(docbaseName, userName, password);
log("Getting
session from docbase " + docbaseName + " (might take some seconds)
...");
session = sMgr.getSession(docbaseName);
log("Session
oppened.");
}
private void releaseSession()
{
sMgr.release(session);
log("Session
closed.");
}
private
IDfSessionManager createSessionManager(String docbase, String user, String
pass) throws Exception {
IDfClientX
clientx = new DfClientX();
IDfClient
client = clientx.getLocalClient();
IDfSessionManager
sMgr = client.newSessionManager();
IDfLoginInfo
loginInfoObj = clientx.getLoginInfo();
loginInfoObj.setUser(user);
loginInfoObj.setPassword(pass);
loginInfoObj.setDomain(null);
sMgr.setIdentity(docbase,
loginInfoObj);
return sMgr;
}
private void doCheckout() throws DfException {
log("Checkout
start ...");
IDfClientX
clientx = new DfClientX();
IDfCheckoutOperation
operation = clientx.getCheckoutOperation();
//iterate over
all <docbaseobject> inner elements
for (DocBaseObject
docbaseObj : docbaseobjects) {
IDfSysObject
sysObj = (IDfSysObject) session.getObjectByQualification("dmc_jar
where object_name='" + docbaseObj.getJarobject() + "'");
if (sysObj == null) {
log("Object:
"
+ docbaseObj.getJarobject() + " can not be found.");
continue;
}
if
(sysObj.isCheckedOut() == true) {
log("Object:
"
+ docbaseObj.getJarobject() + " is already checked out.");
continue;
}
operation.add(sysObj);
log("Object:
"
+ docbaseObj.getJarobject() + " added to Checkout Operation.");
}
executeOperation(operation);
log("Checkout
end.");
}
private void
executeOperation(IDfOperation operation) throws DfException {
boolean executeFlag =
operation.execute();
//if the
operation fails then log all errors
if (!executeFlag) {
IDfList
errorList = operation.getErrors();
String
message = "";
IDfOperationError
error = null;
for (int i = 0; i <
errorList.getCount(); i++) {
error
= (IDfOperationError) errorList.get(i);
message
+= error.getMessage();
}
log("Errors:" + message);
}
else {
log("Checkout
Operation ends successful");
}
}
private void doCheckin() throws DfException {
log("Checkin
start ...");
//iterate over
all <docbaseobject> inner elements
for (DocBaseObject
docbaseObj : docbaseobjects) {
IDfSysObject
sysObj = (IDfSysObject) session.getObjectByQualification("dmc_jar
where object_name='" + docbaseObj.getJarobject() + "'");
if (sysObj == null) {
log("Object:
"
+ docbaseObj.getJarobject() + " can not be found.");
continue;
}
if
(sysObj.isCheckedOut() == false) {
log("Object:
"
+ docbaseObj.getJarobject() + " is not checked out.");
continue;
}
sysObj.setFile(docbaseObj.getJarfile());
sysObj.checkin(false, "CURRENT");
log("Object:
"
+ docbaseObj.getJarobject() + ", file: " + docbaseObj.getJarfile() + " checked
in.");
}
log("Checkin
end.");
}
public static class DocBaseObject extends Task {
private String jarfile;
private String jarobject;
public DocBaseObject()
{
}
public
DocBaseObject(String file, String object) {
jarfile = file;
jarobject = object;
}
public String
getJarfile() {
return jarfile;
}
public void
setJarfile(String localfile) {
this.jarfile = localfile;
}
public String
getJarobject() {
return jarobject;
}
public void
setJarobject(String docbaseObject) {
this.jarobject = docbaseObject;
}
}
}
The last thing we should do is to package this in jar file
“checkoutcheckin.jar” to declare the task in build.xml and “voila” the job is
done. ;)
Here an example how I use it.
<!-- DFC
classpath -->
<path
id="dfc.classpath">
<pathelement
location="${dfc.path}/dfc.jar"
/>
…
…
</path>
Class com.saipem.dams.ant.CheckOutCheckIn
is using DFC classes, so we need to add dfc classes to classpath
too.
<!—Checkin
checkout task definition-->
<taskdef
name="checkoutcheckin"
classname="com.saipem.dams.ant.CheckOutCheckIn">
<classpath>
<pathelement
location="${dams_web.location}/config/${build.env}"
/>
<pathelement
location="${dams_tools.location}/dist/checkoutcheckin.jar"
/>
</classpath>
<classpath
refid="dfc.classpath"
/>
</taskdef>
<!-- Compiles SBO
interfaces-->
<target
name="compile-sbo-interfaces">
<echo
message="Compiling SBO interfaces ..."
/>
<delete
dir="${sbo.location}/build/interfaces"
/>
<mkdir
dir="${sbo.location}/build/interfaces"
/>
<javac
destdir="${sbo.location}/build/interfaces"
excludes="com/example/sbo/impl/*.java"
debug="true"
debuglevel="${debuglevel}"
source="${source}"
target="${target}"
encoding="8859_1">
<src
path="${sbo.location}/src"
/>
<classpath
refid="dfc.classpath"
/>
</javac>
<delete
dir="${sbo.location}/dist/interfaces"
/>
<mkdir
dir="${sbo.location}/dist/interfaces"
/>
<zip
destfile="${sbo.location}/dist/interfaces/interfaces.jar"
encoding="UTF8"
duplicate="preserve">
<zipfileset
dir="${sbo.location}/build/interfaces"
includes="**/*.class"
/>
</zip>
<checkoutcheckin>
<docbaseobject
jarfile="${sbo.location}/dist/interfaces/interfaces.jar
" jarobject="SBO_example_interfaces"
/>
</checkoutcheckin>
</target>
Thank you for your
attention, will see on next article ;) Feel free to comment.
