Friday, November 16, 2012

Creating video tutorials in Windows


If you ever needed to introduce your application(s)/technology to new developers or just create an end user tutorials, here are a few tips that helped me when I was creating instructional videos.

I used CamStudio video capture software and iWisoft video converter. With first application, you will record your video and with second application, you can convert it to desired format. After that, you might want to integrate something like  JWPlayer  in your Wiki site (if you do not have one already) and play the videos.

My setting for video codec is Cinepac Codec by Radius and Volume options are set to default mic and PCM format. When converting, I usually select MP4 format (Apple TV MPEG-4). This should cut the file size ~3 times and still retain the good quality of the recording. You can, of course, adjust more video/audio settings for different formats using only CamStudio.

When recording instructional videos please keep in mind to:

  • Speak slowly and clearly
  • Prepare your concept in advance and practice if you need to
  • Keep your videos short and to the point (15 min/video should be enough as users need to absorb a lot of information in short time)
  • Start the video with agenda that is not too complex and yet clearly states what the intent of the video is

Please let me know if you have a better approach or suggestion and if this information helped you.

Thanks.

Monday, October 01, 2012

Accessing Maven Profiles

I have just spent some time trying to figure out how to determine which profiles are active  during the build using Maven. This functionality would be useful if you needed to put your profile activation in JAR MANIFEST file if your project supported various versions of dependency files (for example different servers, portals or Ajax libraries ...) and in case that your version information did not include this.

Here is a snippet that will make you life easier using GMaven plugin:

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.gmaven</groupId>
                <artifactId>gmaven-plugin</artifactId>
                <version>1.4</version>
                <executions>
                    <execution>
                        <phase>generate-resources</phase>
                        <goals>
                            <goal>execute</goal>
                        </goals>
                        <configuration>
                            <source>
                                project.properties.setProperty('activatedProfiles','')
                                if(project.parent!=null){
                                project.parent.activeProfiles.each() { item-> project.properties.setProperty('activatedProfiles',project.properties.activatedProfiles + "${item.id} ")}
                                }
                            </source>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Active-Profiles>${activatedProfiles}</Active-Profiles>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>    
</project>

If you know easier way, please let me know.

Friday, September 07, 2012

TOAD for SQL Server - hide empty tables

If you are using SQL server and TOAD and have a lot of empty tables that you do not want to show, you can use Object Explorer filter to add this code to prevent them from being shown:

ISNULL((SELECT sum(spart.rows) 
FROM sys.partitions spart 
WHERE spart.object_id = obj.object_id 
AND spart.index_id < 2), 0) <> 0 


Thanks TOAD forum for the help!

Wednesday, September 05, 2012

Displaying jBPM diagram of the current process

In large enough processes, user might need to see where in the diagram process stopped. Now jBPM console comes with this, but to actually integrate it with front end application, I had to change it slightly. Code base used was from bpm-console. First part is setting up properties with the location of your Guvnor (jbpm.console.properties):

guvnor.protocol=http
guvnor.host=localhost:8080
guvnor.usr=admin
guvnor.pwd=admin
guvnor.subdomain=drools-guvnor
guvnor.connect.timeout=4000
guvnor.read.timeout=4000
bpm.package=/defaultPackage/package
bpm.type=local

Following is the code (you can remove static if you want):

public class DrawGraph {

        /**
  * Gets the console properties.
  *
  * @return the console properties
  */
 public static Properties getConsoleProperties() {
  Properties properties = new Properties();
  try {  
                  properties.load(DrawGraph.class.getResourceAsStream("/jbpm.console.properties"));
  } catch (Throwable t) {
   //do nothing, defaults will be loaded
  }
  return properties;
 }

    /**
     * Gets the bPM active nodes diagram.
     *
     * @param processInstance the process instance
     * @return the bPM active nodes diagram
     */
    public static String getBPMActiveNodesDiagram(ProcessInstance processInstance) {
        try {
            List<ActiveNodeInfo> activeNodeInfoList = getActiveNodeInfo(processInstance);
            String s = "<div style='width:1024px; height:768px; background-color:#ffffff; overflow:auto;'>"
                + "<div id=\"imageContainer\" style=\"position:relative;top:-1;left:-1;\">" + "<img src=\""
                + getImageData(processInstance) + "\" style=\"position:absolute;top:0;left:0\" />";

            for (ActiveNodeInfo activeNodeInfo : activeNodeInfoList) {
                s += "<div class=\"bpm-graphView-activityImage\" style=\"position:absolute;top:"
                    + Math.round((activeNodeInfo.getActiveNode().getY()))
                    + "px;left:"
                    + Math.round((activeNodeInfo.getActiveNode().getX()))
                    + "px;width:50px;height:50px; z-index:1000;background-image: url(/Project/images/play_red_big.png);background-repeat:no-repeat;\"></div>";
            }
            s += "</div>" + "</div>";
            return s;
        } catch (Exception e) {
            logger.error(e);
            return "<div>Could not obtaing process image. Please consult logs to find more details</div>";
        }
    }

    /**
     * Gets the active node info.
     *
     * @param processInstance the process instance
     * @return the active node info
     * @throws Exception the exception
     */
    @SuppressWarnings("unchecked")
        private static List<ActiveNodeInfo> getActiveNodeInfo(ProcessInstance processInstance) throws Exception {
            Properties properties = getProperties();
            String persistenceEnabled = properties.getProperty("persistence.enabled");

            if ("true".equals(persistenceEnabled)) {
                EntityManagerFactory emf = null;
                if (BPMConstants.IS_JUNIT_TEST) {
                    emf = Persistence.createEntityManagerFactory(properties.getProperty("persistence.persistenceunit.name"));
                } else {
                    try {
                        emf = (EntityManagerFactory) new javax.naming.InitialContext().lookup("java:/myFactory");
                    } catch (NamingException e) {
                        e.printStackTrace();
                    }
                }

                EntityManager em = emf.createEntityManager();

                ProcessInstanceLog processInstanceLog = (ProcessInstanceLog) em
                    .createQuery("from ProcessInstanceLog as log where log.processInstanceId = :pid")
                    .setParameter("pid", processInstance.getId()).getSingleResult();

                if (processInstanceLog == null) {
                    throw new IllegalArgumentException("Could not find process instance " + processInstance.getId());
                }
                Map<String, NodeInstanceLog> nodeInstances = new HashMap<String, NodeInstanceLog>();

                for (NodeInstanceLog nodeInstance : (List<NodeInstanceLog>) em
                        .createQuery("from NodeInstanceLog as log where log.processInstanceId = :pid")
                        .setParameter("pid", processInstance.getId()).getResultList()) {
                    if (nodeInstance.getType() == NodeInstanceLog.TYPE_ENTER) {
                        nodeInstances.put(nodeInstance.getNodeInstanceId(), nodeInstance);
                    } else {
                        nodeInstances.remove(nodeInstance.getNodeInstanceId());
                    }
                        }
                if (!nodeInstances.isEmpty()) {
                    List<ActiveNodeInfo> result = new ArrayList<ActiveNodeInfo>();
                    for (NodeInstanceLog nodeInstance : nodeInstances.values()) {
                        boolean found = false;
                        DiagramInfo diagramInfo = getDiagramInfo(processInstance);
                        for (DiagramNodeInfo nodeInfo : diagramInfo.getNodeList()) {
                            if (nodeInfo.getName().equals("id=" + nodeInstance.getNodeId())) {
                                result.add(new ActiveNodeInfo(diagramInfo.getWidth(), diagramInfo.getHeight(), nodeInfo));
                                found = true;
                                break;
                            }
                        }
                        if (!found) {
                            throw new IllegalArgumentException("Could not find info for node " + nodeInstance.getNodeId() + " of process "
                                    + processInstanceLog.getProcessId());
                        }
                    }
                    return result;
                }
            } else {
                throw new IllegalArgumentException("Persistence has to be enabled with logging to be able to print process");
            }
            return null;
        }

    /**
     * Gets the diagram info.
     *
     * @param processInstance the process instance
     * @return the diagram info
     * @throws Exception the exception
     */
    private static DiagramInfo getDiagramInfo(ProcessInstance processInstance) throws Exception {
        DiagramInfo result = new DiagramInfo();
        // TODO: diagram width and height?
        result.setWidth(1024);
        result.setHeight(768);
        List<DiagramNodeInfo> nodeList = new ArrayList<DiagramNodeInfo>();
        //be careful here. If BTM transaction manager is set, kruntime is null?!
        if (processInstance.getProcess() instanceof WorkflowProcess) {
            TDefinitions um = null;
            IBindingFactory bfact = BindingDirectory.getFactory(TDefinitions.class);
            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
            String source = getProcessSourceContent(processInstance);
            if (source != null) {
                um = (TDefinitions) uctx.unmarshalDocument(new ByteArrayInputStream(source.getBytes()), null);
            }

            addNodesInfo(nodeList, ((WorkflowProcess) processInstance.getProcess()).getNodes(), "id=", um);
        }
        result.setNodeList(nodeList);
        return result;

    }

    /**
     * Gets the process source content.
     *
     * @param packageName the package name
     * @param assetName the asset name
     * @return the process source content
     * @throws IOException 
     */
    private static String getProcessSourceContent(ProcessInstance processInstance) throws IOException {

        if ("local".equalsIgnoreCase(getConsoleProperties().getProperty("bpm.type", "remote"))) {
            return IOUtils.toString(
                    DrawGraph.class.getResourceAsStream("/resources/" + processInstance.getProcessId() + ".bpmn2"), "UTF-8");
        } else {

            String assetSourceURL = getConsoleProperties().getProperty("guvnor.protocol", "http") + "://"
                + getConsoleProperties().getProperty("guvnor.host", "localhost:8080") + "/"
                + getConsoleProperties().getProperty("guvnor.subdomain", "drools-guvnor") + "/rest/packages"
                + getConsoleProperties().getProperty("bpm.package") + "/assets/" + processInstance.getProcessId() + "/source/";

            try {
                InputStream in = getInputStreamForURL(assetSourceURL, "GET");
                StringWriter writer = new StringWriter();
                IOUtils.copy(in, writer);
                return writer.toString();
            } catch (Exception e) {
                logger.error("Error retrieving asset content: " + e.getMessage());
                return "";
            }
        }

    }

    /**
     * Gets the input stream for url.
     *
     * @param urlLocation the url location
     * @param requestMethod the request method
     * @param guvnorUtils the guvnor utils
     * @return the input stream for url
     * @throws Exception the exception
     */
    private static InputStream getInputStreamForURL(String urlLocation, String requestMethod) throws Exception {
        URL url = new URL(urlLocation);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        connection.setRequestMethod(requestMethod);
        connection.setRequestProperty("User-Agent",
                "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.16) Gecko/20110319 Firefox/3.6.16");
        connection.setRequestProperty("Accept", "text/plain,text/html,application/xhtml+xml,application/xml");
        connection.setRequestProperty("charset", "UTF-8");
        connection.setConnectTimeout(Integer.parseInt(getConsoleProperties().getProperty("guvnor.connect.timeout", "4000")));
        connection.setReadTimeout(Integer.parseInt(getConsoleProperties().getProperty("guvnor.read.timeout", "4000")));
        applyAuth(connection);
        connection.connect();

        BufferedReader sreader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
        StringBuilder stringBuilder = new StringBuilder();

        String line = null;
        while ((line = sreader.readLine()) != null) {
            stringBuilder.append(line + "\n");
        }

        return new ByteArrayInputStream(stringBuilder.toString().getBytes("UTF-8"));
    }

    /**
     * Apply auth.
     *
     * @param connection the connection
     * @param guvnorUtils the guvnor utils
     */
    private static void applyAuth(HttpURLConnection connection) {
        String auth = getConsoleProperties().getProperty("guvnor.usr", "admin") + ":"
            + getConsoleProperties().getProperty("guvnor.pwd", "admin");
        connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBase64String(auth.getBytes()));
    }

    /**
     * Adds the nodes info.
     *
     * @param nodeInfos the node infos
     * @param nodes the nodes
     * @param prefix the prefix
     * @param um the um
     */
    private static void addNodesInfo(List<DiagramNodeInfo> nodeInfos, Node[] nodes, String prefix, TDefinitions um) {
        for (Node node : nodes) {
            Point p = getOffset((String) node.getMetaData().get("UniqueId"), um);
            Integer x = (Integer) node.getMetaData().get("x") + ((Integer) node.getMetaData().get("width"))/2;
            x += p.getX().intValue();
            Integer y = (Integer) node.getMetaData().get("y") + ((Integer) node.getMetaData().get("height"))/2;
            y += p.getY().intValue();
            nodeInfos.add(new DiagramNodeInfo(prefix + node.getId(), x, y, (Integer) node.getMetaData().get("width"), (Integer) node
                        .getMetaData().get("height")));
            if (node instanceof NodeContainer) {
                addNodesInfo(nodeInfos, ((NodeContainer) node).getNodes(), prefix + node.getId() + ":", um);
            }
        }
    }

    /**
     * Gets the offset.
     *
     * @param uniqueId the unique id
     * @param um the um
     * @return the offset
     */
    private static Point getOffset(String uniqueId, TDefinitions um) {
        //get lanes and see if this id belongs
        String laneId = null;
        Point point = new Point();

        if (um != null) {
            start: for (Object rootElement : um.getRootElementList()) {
                    if (rootElement instanceof TProcess) {
                        if (((TProcess) rootElement).getLaneSetList() != null) {
                            for (TLaneSet lanes : ((TProcess) rootElement).getLaneSetList()) {
                                for (TLane lane : lanes.getLaneList()) {
                                    for (String reference : lane.getFlowNodeRefList()) {
                                        if (reference.equalsIgnoreCase(uniqueId)) {
                                            laneId = lane.getId();
                                            break start;
                                        }
                                    }
                                }
                            }
                        }
                    }
            }

            if (laneId != null) {
                for (BPMNDiagram diagram : um.getBPMNDiagramList()) {
                    if (diagram.getBPMNPlane() != null) {
                        for (DiagramElement element : diagram.getBPMNPlane().getDiagramElementList()) {
                            if (element instanceof BPMNShape) {
                                BPMNShape bshape = (BPMNShape) element;
                                if (laneId.equalsIgnoreCase(bshape.getBpmnElement().getName())) {
                                    point.setX(bshape.getBounds().getX());
                                    point.setY(bshape.getBounds().getY());
                                    return point;
                                }
                            }
                        }
                    }
                }
            }
        }

        point.setX(0d);
        point.setY(0d);
        return point;
    }

    /**
    * Gets the diagram url.
    *
    * @param processInstance the process instance
    * @return the diagram url
    */
    private static URL getDiagramURL(ProcessInstance processInstance) {

        try {
            return new URL(getConsoleProperties().getProperty("guvnor.protocol", "http") + "://"
                    + getConsoleProperties().getProperty("guvnor.host", "localhost:8080") + "/"
                    + getConsoleProperties().getProperty("guvnor.subdomain", "drools-guvnor") + "/org.drools.guvnor.Guvnor/package"
                    + getConsoleProperties().getProperty("bpm.package") + "/" + processInstance.getProcessId() + "-image.png");

        } catch (Throwable t) {
            logger.error("Could not get diagram url from Guvnor: " + t.getMessage());
        }

        return null;
    }

    /**
    * Gets the local image data.
    *
    * @return the local image data
    * @throws IOException 
    */
    private static String getImageData(ProcessInstance processInstance) throws IOException {
        String result = "data:image/png;base64,";
        String imageBase64 = null;
        if ("local".equalsIgnoreCase(getConsoleProperties().getProperty("bpm.type", "remote"))) {
            imageBase64 = Base64.encodeBase64String(IOUtils.toByteArray(DrawGraph.class.getResourceAsStream("/resources/"
                            + processInstance.getProcessId() + ".png")));
        } else {
            GuvnorConnectionUtils gcu = new GuvnorConnectionUtils();
            if (gcu.guvnorExists()) {
                imageBase64 = Base64.encodeBase64String(gcu.getProcessImageFromGuvnor(processInstance.getProcessId()));
            }
        }
        return result + imageBase64;
    }
}


To run everything I use JIBX to compile XSD schemas for BPMN2 (you can find them in jbpm-bpmn2-5.2.0.Final.jar). You will need to slightly modify JIBX output with extending classes to compile it, but after that it should work OK.

Before running this, you will need BPMN2 file and PNG in you resources directory (named same as process ID). In case that in the future versions of Designer positioning of the elements inside BPMN2 becomes absolute, then JIBX will not be needed as PNG you can get from Guvnor directly and source will not be parsed as positions are already in the metadata of the node. Currently, as positions are relative we need to calculate the offset to overlay the arrow correctly over PNG. Please also note that I only offset positions for the Lanes and not, for example, from the  Sub-process. You can extend this code to fit your needs.

Usage in xhtml:

<ice:panelGroup>
    <ice:outputText escape="false" value="#{bean.diagramCode}"/>
    <br />
    <div align="right">
        <ice:commandButton value="Close" immediate="true" action="#{bean.cancelAction}" />
    </div>
</ice:panelGroup>

And not to forget, you need to initialize JPAWorkingMemoryDbLogger and add corresponding Entities to persistence.xml (ProcessInstanceLog, NodeInstanceLog, VariableInstanceLog).

As always, if you have any suggestions, please drop me a note.

Thanks to tsurdilo for help!

Friday, August 31, 2012

JSF2 Byte Boolean Checkbox

A few days ago I needed to convert old Icefaces 1.8.2 (JSF1.2) project to Icefaces 3.1 (JSF2) and found a problem when converting Byte to Boolean for the checkboxes. Byte value was generated by Hibernate from database and that is the model that already exists so we really cannot change that. The option with JSF1.2 was to implement Byte to Boolean converter and override rendering kit to call it. JSF2 does not allow this anymore or it is not working (expression library only coerces String to Boolean). After some research, the only option was to automatically generate Boolean getters and setters for existing files. Since there is quite a bit of them spread through different projects, I needed an utility to do this. I ended up writing a small Ruby application for this job. Here is the code:

insert = "
      public void set_r1__b(Boolean _r2_){
        this._r2_ = _r2_!=null&&_r2_?new Byte(\"1\"):new Byte(\"0\");  
      }

      public Boolean get_r1__b(){
        return new Byte(\"1\").equals(this._r2_);
      }

"

Dir.glob("**/*.java"){|file|
  puts "Processing #{file}"
  
  f = File.open(file,"r")
  lines = f.readlines

  result = []
  temp_file_buffer = []

  lines.each { |line| 
    m = /\s*private Byte (is.*)\;.*/.match(line) 
    if m then
      result << m[1]
    end
    temp_file_buffer << line
  }

  #remove last }
  temp_file_buffer.reverse_each { |line|
      if /\}\s*$/.match(line) then
        #better option would be to delete just 1 character } to avoid deleting }} or something else
        temp_file_buffer.delete(line)
        break
      end
  }

  if result.length>0 then
    fw = File.open(file.gsub(/.java/,".rpl"),"w")

    fw.puts(temp_file_buffer)

    result.each { |rl|
      upper = rl.dup
      lower = rl.dup
      upper[0] = upper[0].capitalize
      fw << insert.gsub(/_r1_/,upper).gsub(/_r2_/,lower)
    }

    #insert closing bracket
    fw << "}\n"

    fw.close
  end

  f.close
}

This is by no means perfect code, but it did the job. If you have a better suggestion, please let me know!

Thanks

Tuesday, August 21, 2012

Why use jBPM and Drools


I just wanted to give some intro to the people that are considering using jBPM but still need some picture as where this would fit in their system.

1. What is BPM?


Taken from Wiki:
Business process management (BPM) is a holistic management approach focused on aligning all aspects of an organization with the wants and needs of clients. It promotes business effectiveness and efficiency while striving for innovation, flexibility, and integration with technology. BPM attempts to improve processes continuously. It can therefore be described as a "process optimization process." It is argued that BPM enables organizations to be more efficient, more effective and more capable of change than a functionally focused, traditional hierarchical management approach.

From my perspecitve, simply said, BPM should allow company to circumvent complex development cycles, give more control to customer over what is happening in the process itself and significanetly cut the cost of creating new solutions for the customer as most of components should be reusable. Documentation and help are readily available and development is constant as jBPM is open source.

2. Why use it?


To develop a custom solution is sometimes needed but when exapanding usage and bringing in new technologies where companies are trying to cut costs, we need to be focused on how to implement what we have with anything that might potentialy benefit us and customers at the same time. This means using the knowledge of majority of the people that are alreay experts in the matter but they are not directly working for your company. Maintating and testing such complex sultions takes a lot of time and effort. Also, constantly thinking about new ways to improve functionality and tying the resources into this is not always the best idea, unless your budget allowes you to do it. Contributing to the community (should your company allow it) would be a much better and cost effective way of doing it.

3. What was the need in our company?


We are always faced with the question of how to improve the functionality of the system to allow it to easily integrate with various tools, but on the other hand, to make it so it is stable and reliable as our solution needs to be used in insurance industry. Most of the problems that we are solving are common for the insurance industry but going from customer to customer there are frequent requests to implement a specific functionality that separates one customer from another in the market. Having some competition just makes this process more intense as legacy systems are not so easily replaced.

BPM came into story as we needed more flexibility in our back end systems to allow customers to create and shape processes using only Desinger where we would create custom sevices that can be assembled into different processes with minimal help from development team.

4. How to implement and take the most from this technology?


This is the scenario that we envisioned on how BPM and Drools would be used:


  • Development team creates processes and back-end logic with custom work items where most of the logic that we already have is reused and fortified so it can be called independently
  • Development team creates initial processes to show how BPM should be used 
  • BA team creates initial rules using BRL and DRL file packed into the PKG so we can version every release and use agents to reload resources dynamically 
  • Development team creates integration of the BPM engine into the system
  • Customer starts modifying processes and submit them to Guvnor. These resources are automatically applied (after QA testing and busniess approvals)
  • Customer starts modifying rules by changing and removing old ones and introducing new rules as needed. Rules are dynamically loaded into application (no need for restart or recompiling)
  • Process is iterative and has minimal involvement from IT team (only for implementing new functionality)


When integrating BPM, there are several things to consider:


  1. Is your system stateful or stateless? BPM generaly uses stateful session, so you need to know the bounds and lifecycle of this session even if it is executed briefly.
  2. Where to create your Knowledge Base. Crating knowledge base can take time, so you can consider either creating it in some application scoped object that is initiated once or creating singleton object for the Knowledge Base as you access BPM engine.
  3. How to invoke rules? There is an option to invoke rules through BPM directly, but we chose to do it in the work item code by creating another stateless session. This gives us much more control over which objects are passed into the session and we can reuse code if we want to use Drools without BPM.
  4. How to load resources? KnowledgeBuilderFactory vs KnowledgeAgentFactory. Static vs dynamic. We chose this to be configurable to allow us to load resources from packages and to connect to Guvnor and load resources from there. If you are loading resources from Guvnor, you need to consider that the Guvnor will not only become your source control but integral part of the application. On the other hand, resources can be loaded dynamically from files too, if you choose not to use Guvnor. This allows you to change the process and deploy the resources without touching the application. You should not forget to start the listeners though, if using agent to check for changes in packages.
  5. Transport and security of the user tasks. If you need user tasks, you can use several different types of handlers (WorkItemHandler). Please note that you will need to build/configure some security around those. Sine the source is open, you can change queries that are executed through already defines interface by defining custom mapping-file in persistence.xml. 
  6. Versioning. When you deploy one ID of the process, you will still need the old one as you might have some processes persisted and in need of continuing. You will then copy process and create new version with different ID. When starting new process you will need to use new ID and also have both BPMN resources loaded as the one that is deserializing and continuing will need old definition. The other option is to fail the process or manually convert to new process.
  7. Transaction management. We needed to implement 2 data sources (one XA) to make this work, so plan where your transaction will start, join and where it will commit/rollback.
There are probably many more, but these were important to me.


I hope that I gave you some ideas on why would you choose jBPM in your application and hopefully this will make your customers happy. As always, to find extensive information, please use JBoss help site(s)/forums and manual as there is plenty of information there. You can get a lot of help from IRC too.

Thanks!

Thursday, July 12, 2012

Hunting in Canada

A few weeks ago I passed my Ontario Hunter Education course. I decided to take the course as I felt that I needed to connect more with nature through hunting as something that was common for people to do in the past centuries. Becoming a hunter and hunting is something that I have always wanted to do but somehow never found the time to do it. Well, if you decide to start with this and live in GTA, these resources might help:

1. Ontario Hunters Education Program
2. Ready AIM

The second link is from the company that offers hunting and firearms courses. I have had a great time listening to the courses as people working in Ready AIM are great and knowledgeable. A word of advice, book your courses soon as they get sold quickly.

I decided that I wanted to Bow-hunt but even for that, to get a hunter license, you will need to pass non-restricted firearms course (Canadian Firearms Safety Course). Course is not difficult and you will get a lot of help there.

All the best to the future hunters and please hunt safely and ethically.

Working with jBPM 5


I just wanted to say a few words about jBPM. jBPM is a great product that comes from JBoss and used with several other technologies we can use it to make effective and easy to understand workflow. Our task was to replace current Java based back-end and integrate it loosely with jBPM with possibility to replace BPM engine with some other vendor in the future, if needed. Together with this we would need to modularize our back-end and expose it to BPM adding greatly to the ability for our customers to custom craft and change processes to the way that best fits their business. We already have a great platform for insurance and BPM should make it even better and more versatile. Time to change the process flow and to apply new design should be dramatically cut after BPM is introduced.

After some time of using it I have to say that it is a great product that comes free and that will add a lot of value to already established backend.

In this blog I want to point out to several problems that costed me a lot of time to figure it out and hopefuly this should make understanding jBPM easier.

To start of we needed some documentation and found some basic usages on the JBoss site. It should be enough to start using jBPM but I have to say that initially I was not pleased with the amount of details and some complex usages requirements that we had. We needed following components to make this work:

  1. jBPM libraries
  2. Drools libraries 
  3. Guvnor and Designer setup
  4. Database setup for jBPM

Our deployment and usage was for JBoss 5.1 and Lifray 6. Database version was not much important except that we needed three extra data sources.

  1. Data source to load users from Liferay into BPM database so we can use it to assign human tasks to our users and verify user roles and groups when accessing MINA server
  2. Data source for BPM
  3. Data source for Human Task Service

Please note that all three data sources were implemented using JPA as this is JBoss implementation. The difference in our application is that we needed to combine such approach with Hibernate mapping files that we already had. One of the big issues that I have faced was initiating EntityManagerFactory. Initiating this factory in the middle of the EJB call was not an option, so creating JNDI connection when JBoss started was a way to go.

Sample code:

In persistence.xml:

<property name="jboss.entity.manager.factory.jndi.name" value="java:/jBPMManagerFactory"/>


In your code:

try {
   emf = (EntityManagerFactory) new javax.naming.InitialContext().lookup("java:/jBPMManagerFactory");
} catch (NamingException e) {
   e.printStackTrace();
}



Our code structure was also a bit different from the examples as we had this call structure: Web->Business Delegate->EJB (Stateless)->BPM->Java back-end. The problem is that command based listener is coded in such a way that is has asynchronous code inside that assumes that your session is stateful. In our case this was not good and we needed to rewrite this listener into two classes, one that would create human tasks and other that would process messages with blocking handler. Otherwise, you would need to create some loop to wait for the execution of the code (checking status of the process) in some cases or your EJB call would end up sooner than BPM call.

Some of the other things that need to be watched for is that when you create knowledge base (talking about KnowledgeBuilderFactory), you would preferably do it as a singleton, as creating and importing resources every time takes valuable time. We chose not to bind our application to Guvnor and we decided to use Guvnor only as a development resource (we already have plenty of repositories to worry about).

JBPMHelper is a nice class to start with and I used most of it while rewriting some parts to offer better separation when doing unit tests (during Maven builds) and production usage. We also needed to integrate our configuration engine there and to apply custom created command based listener.

When developing for jBPM pay close attention to ksession.dispose();. You need to call this when you no longer want to work with BPM as resources are not automatically disposed.

Creating custom work item handler is a must in BPM when you have much back-end code, so here are couple of tips that might save you some time. When handling Exceptions, pay close attention to nesting in BPM depending on your structure as you might end up messing up some of the transactions. BPM code executes like this A->B->C->code->C->B->A. In the middle of that you should properly completeWorkItem or abortWorkItem. It is important that you catch your exception and know what to do with it rather that let BPM decide. In our case letting BPM decide what to do was not a good option.

One of the things that I like to do is to group work items so I do not have to write same code over and over again. This means that I would have one input parameter called "function" that would indicate which peace of code would I like to execute once the work item is called. If you have dozens of function, this will save you a lot of time.

Finally, I would like to say a few words about a Designer. A developer from JBoss helped me a lot (Tihomir Surdilovic) with understanding and I wish to thank him for that. For a free product, it offers great possibilities and it is very easy to work with. Your developers and customers will enjoy using it. I say customers as you can expose this directly to them to create shell of a processes that can be later passed on to developer to implement some basic "plumbing". Customer->BA->Developer integration was never more easier.

Designer comes as separate WAR that is deployed together with Guvnor. Guvnor is a repository and the Designer is a tool to craft your processes. Here are a few tips for using and deploying it. When deploying, rename wars to guvnor.war and designer.war Guvnor can find Designer. When creating processes, you can rollback to previous version. Just open process, go to Attributes->Version History and select which version do you want. If you need to delete anything, you need to archive it first and then delete it from the archive. When deploying your resources, I strongly advise you to deploy them as a package (you need to compile them and then package all resources). This way, it will be easy to bundle all the data in a single file and give it a version. The only problem that you might have is the migration of the current processes to the new version if there are saved processes in the database. This means that you will need to convert those manually as they will not be able to deserialize into a new process structure.

These are just a few tips and I intend to write more about BPM and Drools as we progress with development and integration of the BPM into our own platform.

Here are some of the useful links:

  1. BPM User Guide
  2. Guvnor Manual
  3. Drools Introduction
  4. Tihomir's Blog


Thanks

Sunday, May 20, 2012

Shihan Fred Haynes 7th Dan - Aikido Georgetown

On May 7th, we had a fantastic seminar held by Fred Haynes from Victoria, BC. Seminar was held in Georgetown Aikido club. It was my first visit there but, I have to say that the club and people training there are great. We had a good time and there were two senior Dan grading held (4th and 5th Dan). 4th Dan grading was for my Sensei Fred Springer from Seikeikan Yoshinkai Aikido. I have to say that it was a great grading and we all enjoyed watching. These are some of the photographs taken by Dan (he trains with us too :)):


Anyway, grading was great, training even better. Most of the training was focused on center line when doing technique and what Shite needs to do to maintain control of the opponent and keep focus on that line. One of the techniques that we touched was Sankajo (Sankyo) and effectiveness of the pin regarding the position of the Uke shoulder when finishing the technique. This one in particular was focusing on making space between yourself and Uke and keeping Uke's shoulder pinned to the ground. A very nice and effective way to finish the technique. 

I do hope to attend more seminars from Fred H as he has very effective and entertaining way to teach Aikido. If you were at the seminar, please let me know what you think...


Thursday, April 12, 2012

Working with .NET

I have been working with Java most of my professional life, and I have to say that not always has it been easy. In fact, most of the times it was rather difficult to build up knowledge, find and use dependencies, write unit tests and apply correct patterns.

A few days ago, I needed to build an application in .NET as we needed to print and process some Word documents. I have been using C# before but it is not my area of expertise. Obviously, I needed to refresh my knowledge and build an application that can perform well. I was simply amazed how easy was it to pick up basics, start development in Visual Studio and create variations of the application be it, console, form or web. It took mere hours to understand basic concepts, get to know Visual Studio and to be productive. For Java, to achieve the same for the person coming from .NET would take days to achieve same results (think Swing)! I am not a big fan of Microsoft products (being able to run only on Windows machines) but BRAVO Microsoft for making development so easy! It is no wonder that this platform is so widely accepted.

Java development tools are getting there, but having so much diversity can be good and bad at the same time and we will just have to wait and see. Until then, listen to this song (my friend sent this to me) We Code Hard :).

Wednesday, March 07, 2012

Moving from Ant to Maven


I have to admit that I have not used Maven a lot until perhaps mid last year, when I realised how difficult it is becoming to maintain dependencies and builds for J2EE projects using Ant. Many of my colleagues were faced with same problems but most of them still choose to stay with Ant.

Ant was here, it seems, forever. It is well established and mature product and almost all developers understand it and know how to finish the job with it. On the other hand, when Maven came on the first look it seems that developers could not define explicitly what needs to happen when building the project (or at least this was my experience). Everything was implicit with an option to override the default settings. This was a confusing part opposing to the Ant where you needed to define everything explicitly. Not all understood what a project lifecycle was and why it was important. What Maven is today is described here, "What is Maven".  In simple words, these are few benefits that Maven provided to me:
  • Default setting out of the box with need to change build and deployment setting where needed
  • Dependency management, where if I need one dependency, Maven will automatically include all other needed dependency files and will exclude conflicted dependencies
  • Ability to define which dependencies are used for deployment and which are used for test (for example, you need to start in memory database for unit tests and do not want to deploy those jar files to production)
  • If we want to change version of the main dependency, all other relative dependencies will be updated automatically
  • Standardizes project builds through build lifecycle
  • Allows easy separation of code and unit tests

Maven does a lot more, but if we take only items listed, it will be clear how much more your life will become easier. One of the major problems in switching to Maven is how we are thinking about referenced projects (for example if we have dependencies on other projects in the workspace). Maven will not support this (there are workarounds but the only proper way is to create local repository). Maven needs to work with artifacts (basically versions of jar files). To achieve this, all you need to do is to setup in-house Maven repository (for example Sonatype Nexus or Artifactory from JFrog Artifactory) for local files and proxy repositories that are on the Internet. This will enable you to have you own repository with your artifacts (libraries). Many developers will usually avoid this (versioning) as when including them with it would mean that every time they change library project updates with dependencies will need to happen (for every library). On the other hand, working with same version would help avoid updating references. Developers would usually track libraries in the version control systems (or similar) where files are always given the same version under a different release. This, of course, has to change if we want to use Maven, and we need to start versioning the libraries and then uploading them to a local Maven repository. Then we can start including those dependencies in our project, but not as a referenced projects, but as a Maven dependencies. In the case that we need a quick build of the library, we can always install it in our local repository (in Win 7 \Users\User\.m2). This way, it will become available to be included in a project that needs this dependency and later on, it can be published in centralized repository for the rest of the team. This, of course, requires change of culture in the organization. In the end, it pays off big time.

One of the other problems developers are faced with is setting up local environment when starting a new development and making it easy to start being productive (business-wise) and not spending time resolving technical issues with environments and dependencies. Maven does this in an easy way. It not only saves you trouble of uploading you jar files to CVS or SVN, it has different plugins (like Eclipse plugin) that can start projects very easily and where it will setup dependencies from repository based on what is in the pom.xml file. Try it one, and you will never go back to Ant.

So basically, for Maven to work correctly, we need correct directory structure and correctly setup pom.xml file. For directory structure, you can reference this Maven directory layout and for POM setup, this Maven POM. Please note that POM can be simple as just as adding a few lines to describe your artifact and group. (This is like the project name and the package). If you have, for example, m2e plugin for Eclipse, you can see an example of Effective POM that will have a lot of information that you can use to customize your POM. It is up to you how much customization you want or need.

In my experience, even though Maven has an Ant plugin, mixing two of them is not a good idea as it might interfere with Maven build lifecycle (Maven build lifecycle).

And for the end, just to mention that Maven helps with one of the biggest problems that developers have when debugging the code. What happens when the source code from the 3rd party libraries is missing? Maven gets this for you automatically. That means that you can now see what you are debugging when going in depth to figure out you problems.

Please note that this text was written in very simple terms and if you would like to fully understand how Maven works, please refer to Maven site for further documentation. This article is not comparison of Ant vs Maven, but rather it reflects on benefits of having Maven builds in your environment. All projects can be built with both Maven and Ant.

Tuesday, February 07, 2012

Spring and JiBX

When I first heard about JiBX I could not have know that this would be one of the greatest tools for processing XML files that I would use.

It all started when we had a project where a speed and flexibility of XML processing was required and we started of with using XMLBeans as this was already packed with Weblogic server. A little did we know that JiBX will beat XMLBeans in almost every aspect. We had about 100 schemas to process with average of 100 tags and tons of imports. XMLBeans compiled 1 schema for almost a minute and created file that was more that 1MB. JiBX compiled all schemas in a little more than a minute. One jar file was packed at 10 times less space than XMLBeans. When thinking about loading all those files into memory, you will end up using quite a bit of PermGen space. Don't get me wrong, I still use XMLBeans today for some tasks, but I believe that if you can choose a tool for XML processing, choose JiBX and you will not be sorry.

To start off, you would create an XML file (do not forget namespace as this will be used as a package in the jar file) as this is easier than creating XSD from scratch. After that, you can use XMLBeans inst2xsd to convert it to XSD.

..\inst2xsd -design rd -enumerations never -outPrefix test test.xml

When choosing design, you might want to experiment with options. Russian Doll Design is simplest one, so you might want to start with that until you understand how types and elements are used not just in regards to XSD but also how is this going to be reflected in your classes. Turn off enumerations as this will mess up the file. You can add them later manually.

At this point you can copy this to your JiBX directory and create a custom XML (using <custom> - optional) if you have to specifically process some elements and leave others out (cool feature if you need to keep the size of your jar file down, especially if a lot of types and imports are used). One of the advantages of the JiBX is it's high speed and adaptability. For example, if you wanted to pass some custom date in XML, you would need to use string type. But not with JiBX. You can specify how you want to serialize/deserialize the elements when binding them. This is generated by either using predefined classes or creating your own  (you can do that by extending org.jibx.runtime.JodaConvert and then creating your Utility class). A very handy thing to use to adapt to different environments and clients.

JiBX comes with both ANT and MAVEN support and it is very easy to setup. You can find a lot of examples on JiBX site.

When integrating with Spring, it is extremely simple and you can use it to custom build your beans, web services or anything that deals with XML. Spring comes with a lot of support for different Object/XML Mapping and you can read about it here.

Thursday, January 26, 2012

Representing Java classes in diagrams

You probably wanted to display relationships from the Java classes in diagram if you needed to understand how the projects and files are related to each other. Eclipse can show you Call and Type hierarchy, but seeing it all in one graph can help you understand how project is structured. I have created the diagram for the docx4j using small application (using Apache BCEL 5.2) to create it (to import it I converted CSV file to XLSX and used yEd):


Application code that is creating CVS is this:
package ca.sapiens.main;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;

import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;

// TODO: Auto-generated Javadoc
/**
 * The Class MainApp.
 */
public class MainApp {

 /** The result. */
 private static Map<String, Set<String>> result = new HashMap<String, Set<String>>();

 /** The class files. */
 private static Set<File> classFiles = new HashSet<File>();

 /**
  * The main method.
  * 
  * @param args
  *            the arguments
  * @throws IOException
  *             Signals that an I/O exception has occurred.
  * @throws ClassNotFoundException
  *             the class not found exception
  */
 public static void main(String[] args) throws IOException, ClassNotFoundException {
  List<String> regexFilters = new ArrayList<String>();
  regexFilters.add("^java.*");
  regexFilters.add("^org.apache.*");

  List<String> projects = new ArrayList<String>();
  projects.add("c:\\workspace-rapidox\\docx4j-sapiens-2.7.1\\target\\classes\\");

  System.out.println("Starting with file processing");

  int filesCount = 0;

  for (String directory : projects) {
   classFiles.clear();
   System.out.println("Getting class files");
   getAllClassFiles(new File(directory));
   for (File file : classFiles) {
    filesCount++;
    System.out.println("Processing file " + file.getName());
    ClassParser parser = new ClassParser(file.getPath());
    JavaClass clazz = parser.parse();
    int index = clazz.getClassName().indexOf("$");
    if (index == -1)
     index = clazz.getClassName().length();
    String clazzName = clazz.getClassName().substring(0, index);
    if (result.get(clazzName) == null) {
     result.put(clazzName, new HashSet<String>());
    }

    for (Constant constant : clazz.getConstantPool().getConstantPool()) {
     if (constant != null) {
      if (constant instanceof ConstantClass) {
       ConstantUtf8 constantUtf8 = (ConstantUtf8) clazz.getConstantPool().getConstant(
         ((ConstantClass) constant).getNameIndex());
       String name = constantUtf8.getBytes().replaceAll("/", ".");
       // remove inner classes and enumerations
       int index2 = name.indexOf("$");
       if (index2 == -1)
        index2 = name.length();
       // remove arrays indicators
       String correctedName = name.substring(0, index2).replaceFirst("\\[\\w", "")
         .replaceAll("\\;", "");
       boolean pass = true;
       for (String regex : regexFilters) {
        if (Pattern.matches(regex, correctedName)) {
         pass = false;
         System.out.println("Removing " + correctedName);
        }
       }

       if (pass && !clazzName.equalsIgnoreCase(correctedName))
        result.get(clazzName).add(correctedName);
      }
     }
    }
   }
  }

  System.out.println("Writing data...");
  if (result.size() > 0) {
   writeResult("c:\\temp\\output.csv");
  }

  System.out.println("Finished with file processing. Processed " + filesCount + " files");
 }

 /**
  * Gets the all class files.
  * 
  * @param processingFile
  *            the processing file
  * @return the all class files
  */
 private static void getAllClassFiles(File processingFile) {
  if (processingFile.isDirectory()) {
   File[] files = processingFile.listFiles();
   for (File file : files) {
    getAllClassFiles(file);
   }
  } else if (processingFile.isFile() && processingFile.getName().endsWith(".class")) {
   classFiles.add(processingFile);
  }
 }

 /**
  * Write result.
  * 
  * @param filename
  *            the filename
  * @throws IOException
  *             Signals that an I/O exception has occurred.
  */
 private static void writeResult(String filename) throws IOException {
  BufferedWriter out = new BufferedWriter(new FileWriter(filename));

  out.write("Name,Link\n");
  for (Entry<String, Set<String>> entry : result.entrySet()) {
   for (String reference : entry.getValue()) {
    out.write(entry.getKey() + "," + reference + "\n");
   }
  }
  out.close();
 }
}
Once you have run this code, open file in Excel, save as XLSX and then open file in yEd. After that, choose Edge List and fill in your ranges. Import as Circular and then change Layout to Organic (I think that it is faster this way and it looks better). With graphs big as this one, some layouts will be extremely slow. What is useful in the end is that you can select neighboring nodes, and create new document out of that. That should give you a good overview of what your class is using or where it is being used.

Tuesday, January 24, 2012

Ruby log analyzer: rula

This would be my first Ruby application. Name of the application is rula, meaning RUby Log Analyzer. I started this project as I needed to do several searches on the log files that would include previous filters and that would not consume a lot of memory (I intended to run this on the server). I have submitted the code to Git, to location https://github.com/bcavlin/rula, so please feel free to check it out. Application is only working in console mode right now, but I intend to create curses support too. As far as the version, this would be version 0.1. Please feel free to develop it to suite your needs. Here is the image:

Friday, January 20, 2012

SyntaxHighlighter and blogger

If your blog uses SyntaxHighlighter from alexgorbatchev.com then setting it to display items correctly might require a small addition in styles. I needed this to make it look correct (additional style is to limit the length for mobile devices):

...
<!-- this is going in your template -->
<style type="text/css">
    .height_600px_class {height: 600px;}
    .overflow_y_hidden_class {overflow-y: hidden !important;}
</style>

<!--choose one of these for your code -->
<pre class="brush:xml; class-name:'height_600px_class'" style="height:400px; overflow:hidden;">
</pre>

<pre class="brush:xml; class-name:'overflow_y_hidden_class'" style="height:400px; overflow:hidden;">
</pre>
...

JSF, ICEfaces and resetting component values

I just spent some time trying to figure out how to reset the value of the HtmlSelectOneMenu when cancel button is clicked using ICEfaces. The solution is to add actionListener to your ice:commandButton (in this case Cancel) and to find any component that you want to reset. My reset code was:
...
public void resetData(ActionEvent ae){
    ((com.icesoft.faces.component.ext.HtmlInputText) ae.getComponent().getParent().getParent().findComponent("dateComponent")).setValue(null);
    ((com.icesoft.faces.component.ext.HtmlSelectOneMenu) ae.getComponent().getParent().getParent().findComponent("selectComponent")).resetValue();
}
...

Tuesday, January 17, 2012

MyEclipse and JUtils

This morning I needed to generate toString() for the few bean classes, but I could not find JUtils in MyEclipse 9 menus. I checked in the Common/plugins directory and found that it is already there but could not install it. What I did to get JUtils in MyEclipse is, I downloaded JUtils from sourceforge.net unzip it in MyEclipse 9/dropins folder. Restarted eclipse and system reported that it found new plugin. Done.

Thursday, January 12, 2012

Working with graphs: yEd

If you ever worked with Visio or needed to create some graphs, you will appreciate any tool that can simplify the process and as a plus, be freeware. One of such tools that I tried is yEd graph editor. This tools was written  in Java and it is absolutely amazing. It is simple, intuitive and can do everything that Visio can and even more. Just to mention some of the things that I found very useful:
  1. Creating your own shapes very easily
  2. Organizing shapes and lines in different layouts (and I can tell you that it works much better than Viso and it gives amazing results)
  3. Importing graphs from Excel (now this is very useful feature that gives you ability, for example, to have a list of classes in txt file, and to create Excel tables from it which you can import in yEd and entire graph with relationships that you defined will be created for you)
  4. Searching nodes, links and everything else is very simple and powerful as you have many options for search (for example you want to select nodes that are only of specific color)
 

Check out link for yEd Graph Editor if you want to download this tool.

Thursday, January 05, 2012

Spring and Hibernate

Creating configuration for Spring to use Hibernate is not difficult. Basic configuration can look like this, providing that you put in your variables. Just remember that you want annotation based configuration and then you can use @Transactional annotation for your classes/methods. Working with transactions has never been easier.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/your-data-source" />

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mappingResources">
            <list>
                <value>path/to/your/file/File1.hbm.xml</value>
                <value>path/to/your/file/File2.hbm.xml</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
            </props>
        </property>
        <property name="eventListeners">
            <map>
                <entry key="merge">
                    <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" />
                </entry>
            </map>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager"/>

</beans>

Visual Studio and log4net

One of the projects here at Sapiens, required me to add logging to AddOn for the Word. I googled the subject and found a good logging framework, log4net. It is very similar to log4j if one is working with Java, so no surprises there. At first, I had a bit of difficulty on how to initially setup this, but I found a good post on this blog and a few other places. What this blog was missing is that once you download log4net, you need to decide which DLL you want to use, or otherwise, you will get compilation error. You can decide by going to Project->Properties->Application and under Target framework, you will find what is your current setting. You can then navigate to proper DLL.

Also, what I changed is location of my log, and added ${TMP}\myfile.log instead what original author put in place.

For all those experienced in Visual Studio, this would probably not be a problem, but I am a Java developer so this kind of post would help me :).

Spring and IBM MQ Series

Working with IBM MQ Series server can be at some times complicated, but if you follow a few basic steps, you will be able to connect and read/post messages from the MQ server. Posted is the configuration that will enable you to connect to your desired server.

Be careful what you set to transportType property as communication between client to server has to use same type as which is set on server.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:ctx="http://www.springframework.org/schema/context" xmlns:sws="http://www.springframework.org/schema/web-services"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/web-services 
    http://www.springframework.org/schema/web-services/web-services-2.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd">

    <bean id="mqConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
        <property name="port" value="${mqSeriesQueueManagerPortNumber}" />
        <property name="hostName" value="${mqSeriesServerHostAddress}" />
        <property name="channel" value="${mqSeriesQueueManagerChannelName}" />
        <property name="queueManager" value="${mqSeriesQueueManager}" /> 
        <property name="CCSID" value="${mqSeriesQueueManagerCCSID}" />
        <property name="transportType">
            <util:constant static-field="com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPIP" />
        </property>
    </bean>

    <bean id="mqQueue_Reader" class="com.ibm.mq.jms.MQQueue">
        <property name="baseQueueName" value="${mqSeriesQueueName}" />
        <property name="CCSID" value="${mqSeriesQueueManagerCCSID}" />
        <property name="targetClient">
            <util:constant static-field="com.ibm.mq.jms.JMSC.MQJMS_CLIENT_NONJMS_MQ" />
        </property>
    </bean>

    <bean id="jmsQueueConnectionFactory" class="org.springframework.jms.connection.UserCredentialsConnectionFactoryAdapter">
        <property name="targetConnectionFactory" ref="mqConnectionFactory" />
        <property name="username" value="${mqSeriesUserName}" />
        <property name="password" value="${mqSeriesPassword}" />
    </bean>

    <bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.DynamicDestinationResolver"/>

    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="jmsQueueConnectionFactory" />
        <property name="destinationResolver" ref="jmsDestinationResolver" />
        <property name="pubSubDomain" value="false" />
        <property name="receiveTimeout" value="10000" />
    </bean>

    <bean id="messageListener" class="your.jms.JmsQueueListener"/>

    <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        <property name="connectionFactory" ref="jmsQueueConnectionFactory" />
        <property name="destination" ref="mqQueue_Reader" />
        <property name="messageListener" ref="messageListener" />
        <property name="receiveTimeout" value="3000" />
        <property name="maxMessagesPerTask" value="8" />
        <property name="autoStartup" value="true" />
        <property name="acceptMessagesWhileStopping" value="false" />
        <property name="maxConcurrentConsumers" value="3"/>
    </bean> 

</beans>

Wednesday, January 04, 2012

Spring configuration: web.xml

When dealing with web.xml there are only few basic step that you can implement and have your application running Spring in no time.

This is initialization:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <resource-ref>
        <res-ref-name>jdbc/your-data-source</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

This is configuration if you have web services:

    <servlet>
        <servlet-name>spring-web-service</servlet-name>
        <servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
        <init-param>
            <param-name>transformWsdlLocations</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-web-service-servlet.xml </param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-web-service</servlet-name>
        <url-pattern>/web-service/*</url-pattern>
    </servlet-mapping>

This is configuration if you have regular servlets:

    <servlet>
        <servlet-name>spring-common</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-common-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-common</servlet-name>
        <url-pattern>/spring-common/*</url-pattern>
    </servlet-mapping>

Please be mindful about who loads which configuration file and at what time. For example, main context file is loaded in the beginning (when you deploy the application), but ws or servlet configuration might be initialized once you access them by the container and not by the Spring (depending on your configuration).

Tuesday, January 03, 2012

Working with VIM

VIM is one of the most useful editors that I have worked with (even though you will need a lot of time to learn and remember all commands). What you can accomplish with it is simply amazing, just if you remember some basic commands. The only other tools that I prefer more is Eclipse, but only because I work with Java most of the time.

Anyway, I just though to publish my config file, just in case anyone is having difficult time to get their own configuration. I copied most of mine from this blog, and changed a few things to better suit my needs. (BTW, config if located in your /Users/username/_vimrc file in Windows 7. I often find myself editing the file in Program Files/Vim directory :)).

Here is the config:

set nocompatible
source $VIMRUNTIME/mswin.vim
behave mswin

set diffexpr=MyDiff()
function MyDiff()
  let opt = '-a --binary '
  if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
  if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
  let arg1 = v:fname_in
  if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
  let arg2 = v:fname_new
  if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
  let arg3 = v:fname_out
  if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
  let eq = ''
  if $VIMRUNTIME =~ ' '
    if &sh =~ '\<cmd'
      let cmd = '""' . $VIMRUNTIME . '\diff"'
      let eq = '"'
    else
      let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
    endif
  else
    let cmd = $VIMRUNTIME . '\diff'
  endif
  silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq
endfunction

" Basics {
    set nocompatible " explicitly get out of vi-compatible mode
    set noexrc " don't use local version of .(g)vimrc, .exrc
    set background=dark " we plan to use a dark background
    set cpoptions=aABceFsmq
    "             |||||||||
    "             ||||||||+-- When joining lines, leave the cursor 
    "             |||||||      between joined lines
    "             |||||||+-- When a new match is created (showmatch) 
    "             ||||||      pause for .5
    "             ||||||+-- Set buffer options when entering the 
    "             |||||      buffer
    "             |||||+-- :write command updates current file name
    "             ||||+-- Automatically add <CR> to the last line 
    "             |||      when using :@r
    "             |||+-- Searching continues at the end of the match 
    "             ||      at the cursor position
    "             ||+-- A backslash has no special meaning in mappings
    "             |+-- :write updates alternative file name
    "             +-- :read updates alternative file name
    syntax on " syntax highlighting on
" }


" General {
    filetype plugin indent on " load filetype plugins/indent settings
    set autochdir " always switch to the current file directory 
    set backspace=indent,eol,start " make backspace a more flexible    
    set backupdir=c:/tmp/backup " where to put backup files
    set clipboard+=unnamed " share windows clipboard
    set directory=c:/tmp " directory to place swap files in
    set fileformats=unix,dos,mac " support all three, in this order
    set hidden " you can change buffers without saving
    set iskeyword+=_,$,@,%,# " none of these are word dividers 
    set mouse=a " use mouse everywhere
    set noerrorbells " don't make noise
    set whichwrap=b,s,h,l,<,>,~,[,] " everything wraps
    "             | | | | | | | | |
    "             | | | | | | | | +-- "]" Insert and Replace
    "             | | | | | | | +-- "[" Insert and Replace
    "             | | | | | | +-- "~" Normal
    "             | | | | | +-- <Right> Normal and Visual
    "             | | | | +-- <Left> Normal and Visual
    "             | | | +-- "l" Normal and Visual (not recommended)
    "             | | +-- "h" Normal and Visual (not recommended)
    "             | +-- <Space> Normal and Visual
    "             +-- <BS> Normal and Visual
    set wildmenu " turn on command line completion wild style
    " ignore these list file extensions
    set wildignore=*.dll,*.o,*.obj,*.bak,*.exe,*.pyc,
                    \*.jpg,*.gif,*.png
    set wildmode=list:longest " turn on wild mode huge list
" }
" Vim UI {
    set cursorline " highlight current line
    set incsearch " BUT do highlight as you type you 
                   " search phrase
    set laststatus=2 " always show the status line
    set lazyredraw " do not redraw while running macros
    set linespace=0 " don't insert any extra pixel lines 
                     " betweens rows
    set listchars=tab:>-,trail:- " show tabs and trailing 
    set matchtime=5 " how many tenths of a second to blink 
                     " matching brackets for
    set nohlsearch " do not highlight searched for phrases
    set nostartofline " leave my cursor where it was
    set novisualbell " don't blink
    set number " turn on line numbers
    set numberwidth=5 " We are good up to 99999 lines
    set report=0 " tell us when anything is changed via :...
    set ruler " Always show current positions along the bottom
    set shortmess=aOstT " shortens messages to avoid 
                         " 'press a key' prompt
    set showcmd " show the command being typed
    set showmatch " show matching brackets
    set statusline=%F%m%r%h%w[%L][%{&ff}]%y[%p%%][%04l,%04v]
    "              | | | | |  |   |      |  |     |    |
    "              | | | | |  |   |      |  |     |    + current 
    "              | | | | |  |   |      |  |     |       column
    "              | | | | |  |   |      |  |     +-- current line
    "              | | | | |  |   |      |  +-- current % into file
    "              | | | | |  |   |      +-- current syntax in 
    "              | | | | |  |   |          square brackets
    "              | | | | |  |   +-- current fileformat
    "              | | | | |  +-- number of lines
    "              | | | | +-- preview flag in square brackets
    "              | | | +-- help flag in square brackets
    "              | | +-- readonly flag in square brackets
    "              | +-- rodified flag in square brackets
    "              +-- full path to file in the buffer
" }

" Text Formatting/Layout {
    set completeopt= " don't use a pop up menu for completions
    set expandtab " no real tabs please!
    set formatoptions=rq " Automatically insert comment leader on return, 
                          " and let gq format comments
    set ignorecase " case insensitive by default
    set infercase " case inferred by default
    set wrap " do not wrap line
    set linebreak
    set shiftround " when at 3 spaces, and I hit > ... go to 4, not 5
    set smartcase " if there are caps, go case-sensitive
    set shiftwidth=4 " auto-indent amount when using cindent, 
                      " >>, << and stuff like that
    set softtabstop=4 " when hitting tab or backspace, how many spaces 
                       "should a tab be (see expandtab)
    set tabstop=8 " real tabs should be 8, and they will show with 
                   " set list on
" }

" Folding {
    set foldenable " Turn on folding
    set foldmarker={,} " Fold C style code (only use this as default 
                        " if you use a high foldlevel)
    set foldmethod=marker " Fold on the marker
    set foldlevel=100 " Don't autofold anything (but I can still 
                      " fold manually)
    set foldopen=block,hor,mark,percent,quickfix,tag " what movements
                                                      " open folds 
    function SimpleFoldText() " {
        return getline(v:foldstart).' '
    endfunction " }
    set foldtext=SimpleFoldText() " Custom fold text function 
                                   " (cleaner than default)
" }

" Plugin Settings {
    let b:match_ignorecase = 1 " case is stupid
    let perl_extended_vars=1 " highlight advanced perl vars 
                              " inside strings

    " TagList Settings {
        let Tlist_Auto_Open=0 " let the tag list open automagically
        let Tlist_Compact_Format = 1 " show small menu
        let Tlist_Ctags_Cmd = 'ctags' " location of ctags
        let Tlist_Enable_Fold_Column = 0 " do show folding tree
        let Tlist_Exist_OnlyWindow = 1 " if you are the last, kill 
                                        " yourself
        let Tlist_File_Fold_Auto_Close = 0 " fold closed other trees
        let Tlist_Sort_Type = "name" " order by 
        let Tlist_Use_Right_Window = 1 " split to the right side
                                        " of the screen
        let Tlist_WinWidth = 40 " 40 cols wide, so i can (almost always)
                                 " read my functions
        " Language Specifics {
            " just functions and classes please
            let tlist_aspjscript_settings = 'asp;f:function;c:class' 
            " just functions and subs please
            let tlist_aspvbs_settings = 'asp;f:function;s:sub' 
            " don't show variables in freaking php
            let tlist_php_settings = 'php;c:class;d:constant;f:function' 
            " just functions and classes please
            let tlist_vb_settings = 'asp;f:function;c:class' 
        " }
    " }
" }

" Mappings {
    " this is to enable line by line browsing when wrap is on, or otherwise,
    " vim will skip entire line
    map <Down> gj
    map <Up> gk

    " space / shift-space scroll in normal mode
    noremap <S-space> <C-b>
    noremap <space> <C-f>
" }

" Autocommands {
    " Ruby {
        " ruby standard 2 spaces, always
        au BufRead,BufNewFile *.rb,*.rhtml set shiftwidth=2 
        au BufRead,BufNewFile *.rb,*.rhtml set softtabstop=2 
    " }
    " Notes {
        " I consider .notes files special, and handle them differently, I
        " should probably put this in another file
        au BufRead,BufNewFile *.notes set foldlevel=2
        au BufRead,BufNewFile *.notes set foldmethod=indent
        au BufRead,BufNewFile *.notes set foldtext=foldtext()
        au BufRead,BufNewFile *.notes set listchars=tab:\ \ 
        au BufRead,BufNewFile *.notes set noexpandtab
        au BufRead,BufNewFile *.notes set shiftwidth=8
        au BufRead,BufNewFile *.notes set softtabstop=8
        au BufRead,BufNewFile *.notes set tabstop=8
        au BufRead,BufNewFile *.notes set syntax=notes
        au BufRead,BufNewFile *.notes set nocursorcolumn
        au BufRead,BufNewFile *.notes set nocursorline
        au BufRead,BufNewFile *.notes set guifont=Consolas:h12
        au BufRead,BufNewFile *.notes set spell
    " }
    au BufNewFile,BufRead *.ahk setf ahk 
" }

" GUI Settings {
if has("gui_running")
    " Basics {
        colorscheme molokai " my color scheme (only works in GUI)
        set columns=180 " perfect size for me
        set guifont=Consolas:h12 " My favorite font
        set guioptions+=cerbm 
        "               ||
        "               |+-- use simple dialogs rather than pop-ups
        "               +  use GUI tabs, not console style tabs
        set lines=55 " perfect size for me
        set mousehide " hide the mouse cursor when typing
    " }
endif
" }

" Useful stuff {
" I use this when publishing code to blog
function HtmlEscape()
    silent %s/&/\&amp;/eg
    silent %s/</\&lt;/eg
    silent %s/>/\&gt;/eg
    silent %s/©/\&copy;/eg
endfunction

map <F12> <ESC>:call HtmlEscape()<CR>
" }


Spring configuration: applicationContext

When I started working with Spring framework, I immediately recognized the value and simplicity of using such framework to develop and maintain J2EE applications. It is collection of best practices for coding, great design patterns implementation (some of them), and fantastic guideline for putting enterprise level applications together. However, starting with Spring can sometime be overwhelming experience, so I would like to create a few posts that would make this job easier. This is just one of the templates that works for me, but with Spring you have infinite number of possibilities on how to integrate and develop you code.

More about Spring framework can be found at Spring documentation. Of course, Springsource (and community) have created many other additions and standalone products that fit well with Spring. Please feel free to explore this product.

File included in this post would be the first applicationContext.xml file that will be loaded from the web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:ctx="http://www.springframework.org/schema/context" xmlns:sws="http://www.springframework.org/schema/web-services"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/web-services 
    http://www.springframework.org/schema/web-services/web-services-2.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <!-- enable configuration with annotations -->
    <context:annotation-config />

    <!-- we want to use AspectJ proxy (Spring proxy is limited) -->
    <aop:aspectj-autoproxy />

    <!-- scan for all annotations in this package -->
    <ctx:component-scan base-package="my.package.structure" />

    <!-- load log4j configuration -->
    <!-- custom properties to get Properties when crating them -->
    <!-- should have private Properties customProperties, and should be set when loading log4j --> 
    <bean id="log4jPropertyConfigurer"
        class="my.package.structure.properties.CustomPropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:log4j.properties</value>
            </list>
        </property>
        <property name="order" value="0"></property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>

    <!--configure log4j -->
    <!-- call this in your constructor to init log4j: org.apache.log4j.PropertyConfigurator.configure(properties.getCustomPropeties()) -->
    <bean id="applicationLog4j" class="my.package.structure.properties.log4j.Log4jPropertyConfigurer">
        <constructor-arg index="0" ref="log4jPropertyConfigurer" />
    </bean>        

    <!-- load additional properties -->
    <bean id="propertyConfigurer"
        class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:application.properties</value>
                <value>classpath:jdbc.properties</value>
                <value>classpath:messages.properties</value>
                <!-- This should be loaded last -->
                <value>file:override.properties</value>
            </list>
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean> 

    <bean id="messageSource"
        class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>messages</value>
                <value>messages_en_US</value>
            </list>
        </property>
    </bean>

    <!-- import hibernate or any other Spring xml -->
    <import resource="applicationContext-hibernate.xml" />  

</beans>

Windows 7 Unidentified Network and VMWare

I have spent some time trying to figure out why if Windows 7 showing Unidentified Network constantly. The reason was that I have VMWare installed and it is causing Windows to assign it's adapters as unidentified.

One of the solutions you can find here: www.moore-logic.com.

Sunday, January 01, 2012

Merging Word documents with docx4j

Recently I needed to merge some Word .docx  documents and the tools that we chose for this was docx4j (www.docx4java.org). This is library for Java for working with Microsoft Open XML. There we two things that we needed to accomplish:

  1. Binding XML to various templates
  2. Merging documents as a result of the binding

I will write about merging documents as binding them is already explained well in docx4j site. Author of docx4j also offers commercial package for merging documents but if you want to try it for yourself, here are couple of things that I managed to do and got pretty decent results.

In version 2.7.1 docx4j you can work with java.util.File or java.io.InputStream. First one will do a god job if you have file present in your drive and second one if you keep content in the database (for example).  When merging Word documents you have to take care of relationships in the document itself. There are several elements that have relationships that can span through the document, but we were interested in just a few of them (images, footers and headers). It is worth to mention that if you miss one relationship, your document will be unreadable (in most cases). These are listed as resources and have references that you can use in your paragraphs.

So, to start we would:

  1. Load our initial file in WordprocessingMLPackage (this is the file where we want to attach the rest of the files, so in the end they look as one)
  2. Create unique section template
  3. Reset sections (this will serve the purpose of removing all references from the existing template, remember that section defines page layout)
  4. Remove body section (we can add this in the end)
  5. Loop through the attachment files (if you do not have sections separating pages, you might add page breaks)
  6. Copy relationships that you are interested in
  7. Copy elements
  8. If you do not want page breaks, then you can add empty section
  9. Add body section
  10. Reapply all headers and footers to empty sections

This all might sound complicated, but in the end, once you get to know the structure of the WordprocessingMLPackage, it becomes easier.

These are the code snippets that might be useful:

//...
public class MergeUtil implements IMergeUtil {

    //...

    private void mergeDocxFiles(WordprocessingMLPackage initialFile, List<WordprocessingMLPackage> attachementFiles,
            String outputFile) throws Exception {
        //...
        resetSections(wordMLPackageDest);
        //...
        addEmptySection(wordMLPackageDest, SectionType.PARAGRAPH);

        for (WordprocessingMLPackage wordprocessingMLPackage : attachementFiles) {
            //...
            traverseAndCopyRelationships(wordprocessingMLPackage.getPackage().getRelationshipsPart());
            traverseAndCopyElements(wordprocessingMLPackage.getPackage().getRelationshipsPart(),
                    wordprocessingMLPackage.getMainDocumentPart().getContent());
            //...

        }

        addEmptySection(wordMLPackageDest, SectionType.BODY);
        assignHeaderFooterData(wordMLPackageDest);
        //...                

    }

    //...

    private void addPageBreak() {
        logger.debug("Adding page break");
        org.docx4j.wml.P p = new org.docx4j.wml.P();
        org.docx4j.wml.R r = new org.docx4j.wml.R();
        org.docx4j.wml.Br br = new org.docx4j.wml.Br();
        br.setType(STBrType.PAGE);
        r.getContent().add(br);
        p.getContent().add(r);
        wordMLPackageDest.getMainDocumentPart().addObject(p);
    }

    @SuppressWarnings({ "restriction", "rawtypes" })
        private void traverseAndCopyElements(RelationshipsPart rp, List<Object> content) throws InvalidFormatException {
            for (Object o : content) {

                //...
                findResourceById(rp, ((org.docx4j.dml.picture.Pic) o6).getBlipFill().getBlip()
                        //...
                        .getEmbed());
                findResourceByName(wordMLPackageDest.getPackage().getRelationshipsPart(),
                        imageRelPartName);
                //...  
            }
        }

    //...        
    private void findResourceById(RelationshipsPart rp, String lastId) {
        for (Relationship r : rp.getRelationships().getRelationship()) {
            Part part = rp.getPart(r);
            //...
            if (part.getRelationshipsPart(false) != null) {
                findResourceById(part.getRelationshipsPart(false), lastId);
            }
        }
    }

    private void findResourceByName(RelationshipsPart rp, String imageName) {
        for (Relationship r : rp.getRelationships().getRelationship()) {
            Part part = rp.getPart(r);
            //...
            if (part.getRelationshipsPart(false) != null) {
                findResourceByName(part.getRelationshipsPart(false), imageName);
            }
        }
    }

    private void traverseAndCopyRelationships(RelationshipsPart rp) throws InvalidFormatException {
        for (Relationship r : rp.getRelationships().getRelationship()) {
            Part part = rp.getPart(r);
            if (part != null) {
                //...
                if (part instanceof org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage
                        || part instanceof org.docx4j.openpackaging.parts.WordprocessingML.FooterPart
                        || part instanceof org.docx4j.openpackaging.parts.WordprocessingML.HeaderPart) {
                    //...
                        }

                if (part.getRelationshipsPart(false) != null) {
                    traverseAndCopyRelationships(part.getRelationshipsPart(false));
                }
            }
        }
    }
    //...
    private void resetSections(WordprocessingMLPackage wordMLPackage) throws InvalidFormatException {
        Document doc = (Document) wordMLPackage.getMainDocumentPart().getJaxbElement();

        for (Object o : doc.getBody().getContent()) {
            if (o instanceof org.docx4j.wml.P) {
                if (((org.docx4j.wml.P) o).getPPr() != null) {
                    org.docx4j.wml.PPr ppr = ((org.docx4j.wml.P) o).getPPr();
                    if (ppr.getSectPr() != null) {
                        //...
                    }
                }
            }
        }

        wordMLPackage.getMainDocumentPart().getJaxbElement().getBody().setSectPr(null);
    }
    //...
    private void addEmptySection(WordprocessingMLPackage wordMLPackage, SectionType type) {
        if (type.equals(SectionType.BODY)) {
            org.docx4j.wml.SectPr sectPr = objectFactory.createSectPr();
            sectPr.setPgSz(this.defaultSectionpgSz);
            sectPr.setPgMar(this.defaultSectionpgMar);
            sectPr.setCols(this.defaultSectioncols);
            sectPr.setDocGrid(this.defaultSectiondocGrid);
            wordMLPackage.getMainDocumentPart().getJaxbElement().getBody().setSectPr(sectPr);
        } else {
            //...
        }
    }
    //...
    private void assignHeaderFooterData(WordprocessingMLPackage wordMLPackage) throws InvalidFormatException {
        Document doc = (Document) wordMLPackage.getMainDocumentPart().getJaxbElement();
        int sectionCounter = 0;
        wordMLPackage.getMainDocumentPart().getContent();

        HeaderPart headerPart = new HeaderPart();
        headerPart.setPackage(wordMLPackage);
        headerPart.setJaxbElement(objectFactory.createHdr());
        Relationship rHdr = wordMLPackage.getMainDocumentPart().addTargetPart(headerPart);
        FooterPart footerPart = new FooterPart();
        footerPart.setPackage(wordMLPackage);
        footerPart.setJaxbElement(objectFactory.createFtr());
        Relationship rFtr = wordMLPackage.getMainDocumentPart().addTargetPart(footerPart);

        for (Object o : doc.getBody().getContent()) {
            if (o instanceof org.docx4j.wml.P) {
                if (((org.docx4j.wml.P) o).getPPr() != null) {
                    org.docx4j.wml.PPr ppr = ((org.docx4j.wml.P) o).getPPr();
                    if (ppr.getSectPr() != null) {
                        //...
                        if(!StringUtils.isEmpty(hr.getId()))
                            ppr.getSectPr().getEGHdrFtrReferences().add(hr);
                        //...
                    }
                }
            }
        }

        HeaderReference hr = objectFactory.createHeaderReference();
        hr.setType(HdrFtrRef.DEFAULT);
        FooterReference fr = objectFactory.createFooterReference();
        fr.setType(HdrFtrRef.DEFAULT);
        hr.setId(findRelationshipByTarget(wordMLPackage.getRelationshipsPart(),  String.format("/word/header1_%d.xml", lastHeaderReference)));
        fr.setId(findRelationshipByTarget(wordMLPackage.getRelationshipsPart(),  String.format("/word/footer1_%d.xml", lastHeaderReference)));

        if(!StringUtils.isEmpty(hr.getId()))
            wordMLPackage.getMainDocumentPart().getJaxbElement().getBody().getSectPr().getEGHdrFtrReferences().add(hr);
        if(!StringUtils.isEmpty(fr.getId()))
            wordMLPackage.getMainDocumentPart().getJaxbElement().getBody().getSectPr().getEGHdrFtrReferences().add(fr);
    }

    private String findRelationshipByTarget(RelationshipsPart rp, String target) throws InvalidFormatException {
        //...            
    }
}
Note: All code displayed in upper window is property of Sapiens North America