Tuscany を JavaSE 6 で実行する

Tuscany SCA 0.9.9 の場合

Tuscany 0.9.1 と同様に 0.9.9 も JavaSE 6 で実行できない。
実装も変更されており、Tuscany 0.9.1 よりも動作させるのに手間どった。

一応、以下のようなアスペクトクラスを使う事で動作するようにはなったが、なんとなく実用的とは言い難く、今のところ Tuscany SCA は J2SE5 で実行させるのが無難だと思う。

なお、アスペクトの適用方法は下記の 0.9.1 の場合と同様。

JavaSE6SupportAspect.java
package simple.aspect;

import javax.xml.stream.XMLInputFactory;

import org.jboss.aop.Aspect;
import org.jboss.aop.Bind;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodCalledByMethodInvocation;

import org.apache.tuscany.sca.core.ExtensionPointRegistry;

@Aspect
public class JavaSE6Aspect {

    @Bind(pointcut = "call(* org.apache.tuscany.sca.core.ExtensionPointRegistry->getExtensionPoint(*)) and within(org.apache.tuscany.sca.host.embedded.impl.ReallySmallRuntimeBuilder)")
    public Object newInstanceAdvice(MethodCalledByMethodInvocation inv) throws Throwable {
        Object result = null;

        if (inv.getArguments()[0] == XMLInputFactory.class) {
            result = XMLInputFactory.newInstance();
            ((ExtensionPointRegistry)inv.getTargetObject()).addExtensionPoint(result);
        }
        else {
            result = inv.invokeNext();
        }
        return result;
    }

    @Bind(pointcut = "call(javax.xml.stream.XMLInputFactory javax.xml.stream.XMLInputFactory->newInstance(java.lang.String, java.lang.ClassLoader))")
    public Object xmlAdvice(Invocation inv) throws Throwable {
        return XMLInputFactory.newInstance();
    }
}

Tuscany SCA 0.9.1 の場合

Tuscany 0.9 や 0.9.1 は JavaSE 6 で実行できない。

これは、XMLInputFactory のインスタンス化の箇所が原因のようで、これを修正すれば、とりあえず JavaSE 6 で実行できるようになる。

今回は直接ソースコードを修正するのが面倒だったので、JBossAOP 1.5.5 を使って実行時に処理を置き換える事で実現した。

手順は以下の通り。

  • アスペクト定義クラス作成
  • 実行時にアスペクトを適用
アスペクト定義クラス作成

JavaSE 6 で実行できない原因は、org.apache.tuscany.sca.contribution.service.impl.ContributionRepositoryImpl クラスのコンストラクタ内の以下の箇所で引数に javax.xml.stream.XMLInputFactory を指定している事。

factory = XMLInputFactory.newInstance("javax.xml.stream.XMLInputFactory", getClass().getClassLoader());

そのため、以下のようなアスペクトクラスを作成し、引数無しの XMLInputFactory.newInstance() を使用するように処理を置換する。

JavaSE6SupportAspect.java
package simple.aspect;

import javax.xml.stream.XMLInputFactory;

import org.jboss.aop.Aspect;
import org.jboss.aop.Bind;
import org.jboss.aop.joinpoint.Invocation;

@Aspect
public class JavaSE6SupportAspect {

    @Bind(pointcut = "call(javax.xml.stream.XMLInputFactory javax.xml.stream.XMLInputFactory->newInstance(java.lang.String, java.lang.ClassLoader))")
    public Object newInstanceAdvice(Invocation inv) throws Throwable {
        return XMLInputFactory.newInstance();
    }
}
実行時にアスペクトを適用

JBossAOP 1.5 を使って実行時にアスペクトを適用するには、java コマンドの実行時に jboss.aop.class.path システムプロパティにアスペクトクラスへのパスを指定、-javaagent: に jboss-aop-jdk50.jar ファイルのパスを指定する。(aspect_classes は JavaSE6SupportAspect.class ファイルが配置されているディレクトリ)

>java -Djboss.aop.class.path=aspect_classes -javaagent:C:\jboss-aop_1.5.5.GA\lib-50\jboss-aop-jdk50.jar SimpleClient

Ant を使って実行する場合は以下のような build.xml ファイルを用意する。

Ant 用 build.xml の一部
<target name="run" depends="package">
  <java classname="SimpleClient" fork="yes" >
    <sysproperty key="jboss.aop.class.path" value="aspect_classes" />
    <jvmarg value="-javaagent:C:\jboss-aop_1.5.5.GA\lib-50\jboss-aop-jdk50.jar"/>
    <classpath>
      <path refid="project.classpath" />
    </classpath>
  </java>
</target>