If the iterations of the loop are independent and we don’t need to wait for all tasks to complete before proceeding, we can use an Executor to transform a sequential loop into a parallel tasks execution.

Transform sequential loop into a parallel using ExecutorService and CompletionService

First consider an example which process all task using sequential loop.

Public void SequentialLoop(List elements) {
  for (Element e : elements)
      process(e);
}

Let's modify our code and use an ExecutorService to execute task in parallel.
public void processLoopInParallel(Executor exec, List elements) {
  for (final Element e : elements)
      exec.execute(new Runnable() {
          public void run() { process(e); }
      });
}

The second loop will return more quickly, since all the task are queued to the Executor, rather than waiting for each tasks to complete.

If you want to submit a set of tasks and you want to retrieve the results as they become available, we can use CompletionService

void solve(Executor e, Collection<callable<result>> solvers)
     throws InterruptedException, ExecutionException {
       CompletionService<result> ecs
           = new ExecutorCompletionService<result>(e);
       for (Callable<result> s : solvers)
           ecs.submit(s);
       //retrieve completed task results and use them  
       int n = solvers.size();
       for (int i = 0; i < n; ++i) {
           Result r = ecs.take().get();
           if (r != null)
               use(r);
       }
   }

The advantage of using CompletionService is that it always returns the first completed task result. In this way, we can ensure that we are not waiting for tasks to complete while uncompleted tasks are running in the background.

If you want to submit a set of tasks and wait for them all to complete, you can use ExecutorService.invokeAll

This small post describes the process for upgrading xalan-java version to 2.7.1 to work compatible with Java 1.6.

Xalan-Java is an XSLT processor for transforming XML documents into HTML, text, or other XML document types.

The issues that needs to fix while upgrade XSL to work with Java JDK 1.6 and Xalan 2.7.1 will be discussed here and in this post we will look in to sample examples that help us to create XSL’s to work compatible with these new version.

Please note that the problems identified here work well with Java JDK 1.5. Therefore, these changes require only, if we want our XSL to parse successfully with Java JDK 1.6.

xsl:import

This element must appear as the first child node of xsl:stylesheet or xsl:transform. It should not appear in the end or middle of the stylesheet. Otherwise it throws exception

“Error! xsl:import is not allowed in this position in the stylesheet!”

xsl:template

xsl:template must either have name or match attribute. If the name attribute is omitted then there must be a match attribute. For example, the code

<xsl:template >
    <xsl:text>
    -- </xsl:text>
</xsl:template>
throw exceptions

“Fatal Error! java.lang.RuntimeException: ElemTemplateElement error: xsl:template requires either a name or a match attribute.”



The below code will execute successfully.
<xsl:template name="main">
    <xsl:text>
    -- </xsl:text>
</xsl:template>

xsl:value-of

xsl:value-of cannot be enclosed under xsl:text.

For example, the code
<xsl:text>
    <xsl:value-of select="@name"/>
</xsl:text>

will throw exception

“Error! xsl:value-of is not allowed in this position in the stylesheet!”

The code can directly used to extract the value to output stream.

Use StringBuffer/StringBuilder in XSL

XSL Code such as
<xsl:variable name="allTableNames" select="java:java.lang.StringBuffer.new()" />
<xsl:variable name="void0" select="java:append($allTableNames, concat('', $toAppend))" />

throw exception

java.lang.IllegalArgumentException: argument type mismatch

and java.lang.NullPointerException

The reason is that the org.apache.xalan.extensions.MethodResolver picks a method whose argument types are not converted properly. This was noticed in the new versions of JVM due to the order at which they return all methods available for a given class and the issue is still not resolved yet.
Further information can be refer to

https://issues.apache.org/jira/browse/XALANJ-2374
https://issues.apache.org/jira/browse/XALANJ-2315

I have replaced StringBuilder with Map to correctly transform the XSL.

XSL DTMNodeIterator

Consider the following XSL.
<xsl:variable name="temp_core_alias_value">
    <xsl:choose>
       <xsl:when test="'true'">
          <xsl:text>, CASE WHEN </xsl:text><xsl:text>.
          </xsl:text>
          <xsl:text> IS NULL THEN </xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>,</xsl:text>
            <xsl:text>.</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

<xsl:variable name="temp_core_alias" select="java:put($processedMap,
   $temp_core_alias_value, 'Test Value')"/>
   <xsl:variable name="hasValue"
      select="java:containsKey($processedMap, $temp_core_alias_value)"/>
      <xsl:if test="$hasValue = 'true'">
         <xsl:text>Value exist in Map = </xsl:text>
         <xsl:value-of select="java:get($processedMap, $temp_core_alias_value)"/>
      </xsl:if>
   </xsl:variable>
</xsl:variable>
At this point, we might expect java:containsKey($processedMap,$temp_core_alias_value) to return true and the output of the above as “Value exist in Map = Test Value” But when transform using Xalan-Java 2.7.1, the Map return false and therefore no output appear.

The reason is that the evaluating expression for the temp_core_alias_value variable would return
org.apache.xml.dtm.ref.DTMNodeIterator@e020c9 and therefore, the contains method of the Map would always return false regardless of the key present.

We can transform DTMNodeIterator to normal String form by concatenate an empty string with temp_core_alias_value variable like the following
<xsl:variable name="temp_core_alias_value" select="concat('', $temp_core_alias_value)" />

Adding this line right before put in to the Map would result in the normal expected output.