Wednesday, August 31, 2016

Documentum custom dfs jar generation

Documentum provides documentum foundation services (DFS) jars to talk to the CMS for querying, uploading files. This functionality broke after we have upgraded to JBOSS EAP6 with CXF webservice stack.

We have generated the DFS client using the webservice urls

By using CXF wsconsume
C:\dev\dctm_client>C:\tools\jboss-eap-6.2.0\bin\wsconsume.bat -k http://ecmsvc-sys.xxy.com/emc-dfs/services/core/ObjectService?WSDL -b simple-binding.xml
C:\dev\dctm_client>C:\tools\jboss-eap-6.2.0\bin\wsconsume.bat -k http://ecmsvc-sys.xxy.com/emc-dfs/services/core/SchemaService?WSDL -b simple-binding.xml
C:\dev\dctm_client>C:\tools\jboss-eap-6.2.0\bin\wsconsume.bat -k http://ecmsvc-sys.xxy.com/emc-dfs/services/core/QueryService?WSDL -b simple-binding.xml
C:\dev\dctm_client>C:\tools\jboss-eap-6.2.0\bin\wsconsume.bat -k http://ecmsvc-sys.xxy.com/emc-dfs/services/core/runtime/ContextRegistryService?wsdl -b simple-binding.xml


By using native JAXWS wsimport
c:\Java\jdk1.7.0_60\bin\wsimport.exe http://ecmsvc-sys.xxy.com/emc-dfs/services/core/runtime/ContextRegistryService?wsdl -keep -nocompile -b simple-binding.xml
c:\Java\jdk1.7.0_60\bin\wsimport.exe http://ecmsvc-sys.xxy.com/emc-dfs/services/core/SchemaService?WSDL -keep -nocompile -b simple-binding.xml
c:\Java\jdk1.7.0_60\bin\wsimport.exe http://ecmsvc-sys.xxy.com/emc-dfs/services/core/ObjectService?WSDL -keep -nocompile -b simple-binding.xml
c:\Java\jdk1.7.0_60\bin\wsimport.exe http://ecmsvc-sys.xxy.com/emc-dfs/services/core/QueryService?WSDL -keep -nocompile -b simple-binding.xml

And sample-binding.xml
<jaxb:bindings
    xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
    xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
    jaxb:extensionBindingPrefixes="xjc">
    <jaxb:globalBindings>
        <xjc:simple />
    </jaxb:globalBindings>
</jaxb:bindings>

After generating client and bundled into jar (below pom.xml) dfs services worked perfectly with Jboss EAP6. Also the manual steps can be automated by using maven wsimport and wsconsume plugins.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.emc.dfs</groupId>
<artifactId>dfs-cxf-client</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1-redhat-2</version>
</dependency>

<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.11</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>redhat-techpreview-all-repository</id>
<name>Red Hat Tech Preview repository (all)</name>
<url>http://maven.repository.redhat.com/techpreview/all/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>redhat-techpreview-all-repository</id>
<name>Red Hat Tech Preview repository (all)</name>
<url>http://maven.repository.redhat.com/techpreview/all/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
</releases>
<snapshots>
<enabled>false</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</pluginRepository>
</pluginRepositories>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<warSourceDirectory>WebContent</warSourceDirectory>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}/dfs-cxf-client-1.0.jar</file>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>


To invoke operations on the ObjectService helper use

ObjectServiceHelper helper = new ObjectServiceHelper(dctmCtx.getSvrUser(), dctmCtx.getSvrPwd(),
dctmCtx.getRepositoryName(), dctmCtx.getCtxRegistryUrl(), dctmCtx.getCtxRoot(), ContentTransferMode.BASE_64);
ObjectServicePort serPort =  helper.getServicePort();
And do the actual DFS service operations on the ObjectServicePort
serPort.createPath()
serPort.create(DataPackage)

Delete Coherence Cache entries

To remove the cache entries based on the cache filters...

1. Coherence QueryMap interface provides keySet with filter
   Filter dtfilter = new EqualsFilter("getDate", dt);
   Set kset = cache.keySet(dtfilter );
   for (Object obj : kset) {
     cache.remove(obj);
   }
 
   Cache.remove returns the previous value associated with the key. This is not very efficient.
 
2. Best way to delete the cache entries 
Filter dtfilter = new EqualsFilter("getDate", dt);
this.invokeAll(dtfilter , new ConditionalRemove(AlwaysFilter.INSTANCE));

This code is very efficient and it will not return back any old data. 

How to make spring beans thread safe.

The interviewer question how make spring beans thread safe

Spring beans are singleton. This means there is only one bean instance per spring container.
So by default spring beans are not thread safe. To make them thread safe, one way to do this to
create separate spring bean instance every time the bean is accessed (@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) or scope="prototype" in xml config file)

But the interviewer insisted how to make them threadsafe with out changing the configuration and he gave the hint saying the beans are accessed in the servlet environment.

If the bean is singleton, only way to make them thread safe is to use local variables instead of class instance variables. Or if we need instance variables, only way to make the bean thread safe is to use synchronization or by using the locks.

The interviewer gave another solution to make the beans have no instance variables and all the required data to be preloaded and accessed from HTTP session. However HTTP session is not thread safe. This solution will not work.

Reference: https://coderanch.com/t/361845/Servlets/java/HttpSession-thread-safe

Java List Interview Questions

1. Remove Elements from List 

Lets say if I have a list with 6 elements like this
   ["John", "Smith", "John", "Kris", "John", "Bob"]. Remove the elements from the list with the "John"

Easiest solution is to use iterator

e.g.

List<String> alist = new ArrayList<String>(Arrays.asList("John", "Smith", "John", "Kris", "John", "Bob"));
Iterator<String> iter = alist.iterator();
while(iter.hasNext()) {
String name = (String) iter.next();
if (name.equals("John")) iter.remove();
}
System.out.println("alist: " + alist);


Another solution is to use for loop with looping backwards

for (int i=alist.size()-1; i>=0; i--) {
String name = alist.get(i);
if (name.equals("John")) alist.remove(i);
}
System.out.println("alist: " + alist);

2. How to find an element from List with complexity O(1)

Lets say you have Person Class and with the id_, person obj is uniquely identified

class Person {
private int id_;
String name_;
String email_;

 public Person(int id) {
   id_ = id;
 }

public Person(int id, String name, String email) {
id_ = id;
name_ = name;
email_ = email;
}

public boolean equals(Object obj) {
if (obj == null || !(obj instanceof Person)) return false;
Person pobj = (Person) obj;
if (this.id_ == pobj.id_) return true;
else return false;
}

public int hashCode() {
return super.hashCode() + id_;
}

public String toString() {
return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

}

List<Person> plist = new ArrayList<Person>();
Person p1 = new Person(123, "John Smith", "js@xyz.com");
Person p2 = new Person(124, "Bob Harris", "bh@xyz.com");
Person p3 = new Person(125, "Will Smith", "ws@xyz.com");

plist.add(p1); plist.add(p2); plist.add(p3);


You have reference to the very big person list (lets say plist) and you know the key of one object (lets say 124). How to retrieve the object with the key you have

one Option is to loop through the list and find it

public Person findPerson(List plist, int id) { 
  for (int i=0; i<plist.size(); i++) {
  Person p = plist.get(i);
  if (p.getId() == 124) {
    return p;
  }
}

This has the worst case complexity of O(n). The interviewer asked whether it can be improved with O(1). I said I don't know the answer as list complexity is O(n)

He told me the solution as follows

private Person getPerson(List<Person> plist, int id) {
Person p = new Person(id, "xy", "xy@xyz.com");
int idx = plist.indexOf(p);
return plist.get(idx);

}

but the big problem is list.indexOf(obj) has complexity of O(n). So his solution complexity O(n+1).