2.17 SOAPエージェントメッセージ・ハンドラー

LANSA Integrator

2.17 SOAPエージェントメッセージ・ハンドラー


SOAPエージェントメッセージ・ハンドラー・フレームワークはAxisメッセージ・ハンドラー・フレームワークの制限をなくすために開発されたもので、要求ハンドラーや応答ハンドラーを追加する場合にお勧めの方法です。

Apache Axisメッセージ・ハンドラー・フレームワーク用に開発されたメッセージ・ハンドラーは、SOAPエージェントメッセージ・ハンドラー・フレームワークで使用できます。

特定のSOAPエージェントサービスにメッセージ・ハンドラーを追加するには、SOAPAgentService.propertiesファイルに'service.handlers.サービス名' エントリーを追加します。

SOAPエージェントコマンドOPEN SERVICE (サービス名)が実行されると、実行するプログラムにサービス・クラスとメッセージ・ハンドラー・ファイルが割り当てられます。

 

service.test=com.acme.service.soap.TestService

service.handlers.test=handlers/soapagent-handlers.xml

 

複数のエージェント・サービス構成を1つのファイルに含めることができます。

要求ハンドラーや応答ハンドラーの追加はオプションです。

複数のハンドラー要素を含めることで簡単なメッセージ・ハンドラー・チェーンを作成できます。

要求メッセージ・ハンドラーと応答メッセージ・ハンドラーは、すべてのサービス操作または1つの特定の操作に割り当てることができます。

各ハンドラー要素はゼロ個以上のパラメータ要素で構成できます。

これらのパラメータ要素がインスタンス化され、インスタンス化されたハンドラー・クラスに渡されます。

パラメータ値の属性に中括弧で囲まれた値がある場合、その値はLANSAフィールド名と仮定され、LANSAフィールドの値がハンドラーに渡されます。LANSAフィールドをハンドラー・クラスで使用できるようにするには、CALLコマンドでSERVICE_EXCHANGE(*FIELD)キーワードを使用します。

メッセージ・ハンドラー構成

 

<?xml version="1.0" encoding="utf-8"?>

 

<services>

 

 <!-- Testサービスのすべての操作にSOAPHeaderHandlerを割り当てる-->

 <service name="test">

 

  <request>

    <handler class="com.acme.axis.handler.SOAPHeaderHandler"/>

  </request>

 

  <response>

    <handler class="com.acme.axis.handler.SOAPHeaderHandler"/>

  </response>

 

 </service>

 

 <!-- Testサービスのログイン操作にSecurityHandlerとSOAPHeaderHandlerを割り当てる-->

 <service name="test" operation="login">

 

  <request>

    <handler class="com.acme.axis.handler.SecurityHandler">

      <parameter name="user" value="{USER}"/>

      <parameter name="acme.keyword" value="ABC"/>

    </handler>

    <handler class="com.acme.axis.handler.SOAPHeaderHandler"/>

  </request>

 

 </service>

 

</services>

 

メッセージ・ハンドラー・クラスの例

 

package com.acme.axis.handler ;

 

import java.io.* ;

 

import java.util.Vector ;

 

import org.apache.axis.Message ;

import org.apache.axis.SOAPPart ;

import org.apache.axis.AxisFault ;

import org.apache.axis.MessageContext ;

 

import org.apache.axis.utils.XMLUtils ;

 

import org.apache.axis.message.SOAPBody ;

import org.apache.axis.message.SOAPHeader ;

import org.apache.axis.message.SOAPEnvelope ;

import org.apache.axis.message.SOAPBodyElement ;

import org.apache.axis.message.SOAPHeaderElement ;

import org.apache.axis.message.MessageElement ;

 

import org.apache.axis.message.RPCParam ;

import org.apache.axis.message.RPCElement ;

import org.apache.axis.message.PrefixedQName ;

 

import org.apache.axis.description.ParameterDesc ;

 

import org.apache.axis.encoding.SerializationContext ;

 

import org.w3c.dom.Node ;

import org.w3c.dom.Element ;

import org.w3c.dom.Document ;

import org.w3c.dom.NodeList ;

 

import org.w3c.dom.ls.LSOutput ;

import org.w3c.dom.ls.LSSerializer ;

import org.w3c.dom.ls.DOMImplementationLS ;

 

import org.w3c.dom.bootstrap.DOMImplementationRegistry ;

 

import com.lansa.jsm.JSMTrace ;

import com.lansa.jsm.JSMCommand ;

import com.lansa.jsm.JSMResource ;

 

import com.lansa.jsm.service.ServiceHelper ;

 

public class MyHandler extends org.apache.axis.handlers.BasicHandler

{

    private final static String EMPTY_STRING = "" ;

 

    private final static String ENCODING_UTF8 = "UTF-8" ;

 

    private final static String[] FORM_NAMES = { "", "FORM_STRING", "FORM_INPUTSTREAM", "FORM_SOAPENVELOPE", "FORM_BYTES", "FORM_BODYINSTREAM", "FORM_FAULT", "FORM_OPTIMIZED" } ;

 

    private JSMTrace m_trace = null ;

 

    private JSMResource m_serviceResource = null ;

 

    public void init ()

    {

        /*

            オプション - これはBasicHandlerのinitスタブをオーバーライドする

 

            最初に、initがすべてのハンドラーに対して呼び出される

 

            次に、invokeがすべてのハンドラーに対して呼び出される

 

            最後に、cleanupがすべてのハンドラーに対して呼び出される

 

            以下を使用してハンドラー間で情報を渡すことが可能

 

              MessageContext - setProperty ( String name, Object value )

 

              MessageContext - Object value getProperty ( String name )

        */

    }

 

    public void invoke ( org.apache.axis.MessageContext messageContext ) throws AxisFault

    {

        try

        {

            m_trace = (JSMTrace)getOption ( "jsm.handler.property.trace" ) ;

 

            m_serviceResource = (JSMResource)getOption ( "jsm.handler.property.resource" ) ;

 

            traceOptions () ;

 

            modifyMessage ( messageContext ) ;

        }

        catch ( Exception e )

        {

            throw new AxisFault ( "MyHandler: exception : " + e.toString () ) ;

        }

    }

 

    public void cleanup ()

    {

        /*

            オプション - これはBasicHandlerのcleanupスタブをオーバーライドする

        */

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: cleanup" ) ;

        }

    }

 

    private final void traceOptions ()

    {

        /*

            以下のプロパティはハンドラー・パラメータから生じたものである

        */

 

        String value = (String)getOption ( "acme.keyword" ) ;

 

        /*

            以下のプロパティはJSMサービスで提供される

        */

 

        String type = (String)getOption ( "jsm.handler.property.type" ) ;

 

        String service = (String)getOption ( "jsm.handler.property.service" ) ;

 

        String operation = (String)getOption ( "jsm.handler.property.operation" ) ;

 

        /*

            コマンドを呼び出す

        */

 

        JSMCommand command = (JSMCommand)getOption ( "jsm.handler.property.command" ) ;

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: invoke" ) ;

 

            m_trace.println ( "MyHandler: acme.keyword : " + value ) ;

 

            m_trace.println ( "MyHandler: jsm.handler.property.type : " + type ) ;

 

            m_trace.println ( "MyHandler: jsm.handler.property.service : " + service ) ;

 

            m_trace.println ( "MyHandler: jsm.handler.property.operation : " + operation ) ;

 

            m_trace.println ( "MyHandler: jsm.handler.property.command : " + command.toString () ) ;

        }

    }

 

    private final void modifyMessage ( org.apache.axis.MessageContext messageContext ) throws Exception

    {

        Message message = messageContext.getCurrentMessage () ;

 

        if ( message == null )

        {

            throw new IllegalArgumentException ( "no message available" ) ;

        }

 

        /*

            トレース・メッセージ - 出力は内部フォームによって異なる

        */

 

//        traceMessage ( message ) ;

 

        /*

            SOAP部分

        */

 

        SOAPPart soapPart = (SOAPPart)message.getSOAPPart () ;

 

        int form = soapPart.getCurrentForm () ;

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: current message form : ", FORM_NAMES[form] ) ;

        }

 

        /*

            SOAPエンベロープ - 内部フォームがSOAPEnvelopeに変換される

        */

 

        SOAPEnvelope envelope = soapPart.getAsSOAPEnvelope () ;

 

//        traceEnvelope ( envelope ) ;

 

        /*

            要求または応答を処理する

        */

 

        if ( isRequest () )

        {

            modifyHeader ( envelope ) ;

 

            traceBody ( envelope ) ;

 

//            setRequestMessage1 ( soapPart ) ;

 

//            setRequestMessage2 ( messageContext ) ;

 

            setRequestMessage3 ( messageContext, envelope ) ;

 

            return ;

        }

 

        if ( isResponse () )

        {

            setResponseMessage1 ( messageContext ) ;

 

            return ;

        }

    }

 

    private final void modifyHeader ( SOAPEnvelope envelope ) throws Exception

    {

        Vector vector = envelope.getHeaders () ;

 

        int count = vector.size () ;

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: header count : " + count ) ;

        }

 

        for ( int i=0; i < count; i++ )

        {

            SOAPHeaderElement element = (SOAPHeaderElement)vector.elementAt ( i ) ;

 

            if ( m_trace != null )

            {

                m_trace.println ( "MyHandler: soap header : " + element.getElementName () ) ;

            }

        }

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: add header" ) ;

        }

 

        envelope.addHeader ( createHeader () ) ;

    }

 

    private final SOAPHeaderElement createHeader () throws Exception

    {

        SOAPHeaderElement elementHead = new org.apache.axis.message.SOAPHeaderElement ( "namespace", "AuthHeader" ) ;

 

        MessageElement elementSession = (MessageElement)elementHead.addChildElement ( "SessionId" ) ;

 

        elementSession.addTextNode ( "text" ) ;

 

        elementHead.setActor ( null ) ;

 

        return elementHead ;

    }

 

    private final boolean isRequest ()

    {

        String type = (String)getOption ( "jsm.handler.property.type" ) ;

 

        if ( type.equals ( "request" ) )

        {

            return true ;

        }

 

        return false ;

    }

 

    private final boolean isResponse ()

    {

        String type = (String)getOption ( "jsm.handler.property.type" ) ;

 

        if ( type.equals ( "response" ) )

        {

            return true ;

        }

 

        return false ;

    }

 

    private final void setRequestMessage1 ( SOAPPart soapPart ) throws Exception

    {

        /*

            これを最後のメッセージ変更にする必要がある

 

            Message.writeTo -> SOAPPart.writeToメソッドはバイトをそのまま送信する

 

            この方法では、byte[]内容で行われるFORM変換のリスクがある

        */

 

        if ( m_trace != null )

        {

            m_trace.println ( "Set request message 1 using byte[]" ) ;

        }

 

        byte[] message = "any content sent as bytes".getBytes ( ENCODING_UTF8 ) ;

 

        soapPart.setCurrentMessage ( message, SOAPPart.FORM_BYTES ) ;

    }

 

    private final void setRequestMessage2 ( MessageContext messageContext ) throws Exception

    {

        /*

            この例では、ファイルのバイト内容を使用する

 

            ただし、ドキュメントをbyte[]メモリー内にシリアライズしている

 

            またはSringを作成し、内容の引数として使用する

 

            など..

        */

 

        if ( m_trace != null )

        {

            m_trace.println ( "Set request message 2 using byte[] message" ) ;

        }

 

        File file = new File ( "ENVELOPE_REQUEST.XML" ) ;

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: set resquest message from external file : " + file.getName () ) ;

        }

 

        // String content = "<?xml ...." ;

 

        byte[] content = readFile ( file ) ;

 

        Message requestMessage = new Message ( content ) ;

 

        messageContext.setRequestMessage ( requestMessage ) ;

    }

 

    private final void setRequestMessage3 ( MessageContext messageContext, SOAPEnvelope envelope ) throws Exception

    {

        if ( m_trace != null )

        {

            m_trace.println ( "Set request message 3 using document" ) ;

        }

 

        Document document = envelope.getAsDocument () ;

 

        /*

            ドキュメントを変更する

        */

 

        byte[] content = serializeDocument ( document ) ;

 

        Message requestMessage = new Message ( content ) ;

 

        messageContext.setRequestMessage ( requestMessage ) ;

    }

 

    private final void setResponseMessage1 ( MessageContext messageContext ) throws Exception

    {

        /*

            この例では、ファイルのバイト内容を使用する

 

            ただし、ドキュメントをbyte[]メモリー内にシリアライズしている

 

            またはSringを作成し、内容の引数として使用する

 

            など..

        */

 

        File file = new File ( "ENVELOPE_RESPONSE.XML" ) ;

 

        if ( m_trace != null )

        {

            m_trace.println ( "MyHandler: set response message from external file : " + file.getName () ) ;

        }

 

        byte[] content = readFile ( file ) ;

 

        Message responseMessage = new Message ( content ) ;

 

        messageContext.setResponseMessage ( responseMessage ) ;

    }

 

    private final byte[] serializeDocument ( Document document ) throws Exception

    {

        DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance () ;

 

        DOMImplementationLS implementation = (DOMImplementationLS)registry.getDOMImplementation ( "LS" ) ;

 

        LSOutput output = implementation.createLSOutput () ;

 

        LSSerializer serializer = implementation.createLSSerializer () ;

 

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream ( 4096 ) ;

 

        output.setEncoding ( "utf-8" ) ;

 

        output.setByteStream ( outputStream ) ;

 

        serializer.setNewLine ( "\n" ) ;

 

        serializer.write ( document, output ) ;

 

        return outputStream.toByteArray () ;

    }

 

    private final void traceMessage ( Message message )

    {

        if ( m_trace == null )

        {

            return ;

        }

 

        try

        {

            String fileName = "MYHANDLER_MESSAGE" + ServiceHelper.getSequenceLabel ( m_trace ) + ".XML" ;

 

            FileOutputStream outputStream = new FileOutputStream ( m_trace.createTraceFile ( fileName ) ) ;

 

            message.writeTo ( outputStream ) ;

 

            outputStream.close () ;

        }

        catch ( Throwable t )

        {

            m_trace.print ( t ) ;

        }

    }

 

    private final void traceEnvelope ( SOAPEnvelope envelope )

    {

        if ( m_trace == null )

        {

            return ;

        }

 

        /*

            これはMessageElement - getAsDocumentを使用する

 

               - getAsDocument

                  - getAsString

 

            要素をStringに、パーサーをDocumentに変換する

        */

 

        try

        {

            Document document = envelope.getAsDocument () ;

 

            DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance () ;

 

            DOMImplementationLS implementation = (DOMImplementationLS)registry.getDOMImplementation ( "LS" ) ;

 

            LSOutput output = implementation.createLSOutput () ;

 

            LSSerializer serializer = implementation.createLSSerializer () ;

 

            String fileName = "MYHANDLER_ENVELOPE" + ServiceHelper.getSequenceLabel ( m_trace ) + ".XML" ;

 

            FileOutputStream outputStream = new FileOutputStream ( m_trace.createTraceFile ( fileName ) ) ;

 

            output.setEncoding ( "utf-8" ) ;

 

            output.setByteStream ( outputStream ) ;

 

            serializer.setNewLine ( "\n" ) ;

 

            serializer.write ( document, output ) ;

 

            outputStream.close () ;

        }

        catch ( Throwable t )

        {

            m_trace.print ( t ) ;

        }

    }

 

    private final void traceBody ( SOAPEnvelope envelope ) throws Exception

    {

        if ( m_trace == null )

        {

            return ;

        }

 

        SOAPBody body = (SOAPBody)envelope.getBody () ;

 

        if ( body == null )

        {

            throw new IllegalArgumentException ( "no body available" ) ;

        }

 

        RPCElement operation = getOperation ( body ) ;

 

        if ( operation == null )

        {

            throw new IllegalArgumentException ( "no operation available" ) ;

        }

 

        m_trace.println ( "MyHandler: operation name  : " + operation.getElementName () ) ;

 

        traceParameters ( operation ) ;

    }

 

    private final void traceParameters ( RPCElement operation ) throws Exception

    {

        if ( m_trace == null )

        {

            return ;

        }

 

        Vector vector = operation.getParams () ;

 

        int count = vector.size () ;

 

        m_trace.println ( "MyHandler: parameter count : " + count ) ;

 

        for ( int i=0; i < count; i++ )

        {

            RPCParam parameter = (RPCParam)vector.get ( i ) ;

 

            ParameterDesc parameterDesc = parameter.getParamDesc () ;

 

            Class klazz = parameterDesc.getJavaType () ;

 

            m_trace.println ( "MyHandler: parameter name : " + parameter.getElementName () ) ;

 

            if ( klazz.isArray () )

            {

                m_trace.println ( "MyHandler: parameter type : array of " + klazz.getComponentType().getName () ) ;

            }

            else

            {

                m_trace.println ( "MyHandler: parameter type : " + klazz.getName () ) ;

            }

        }

    }

 

    private final RPCElement getOperation ( SOAPBody body )

    {

        NodeList nodeList = body.getChildNodes () ;

 

        if ( nodeList == null )

        {

            return null ;

        }

 

        int count = nodeList.getLength () ;

 

        if ( count == 0 )

        {

            return null ;

        }

 

        for ( int i=0; i < count; i++ )

        {

            Node node = nodeList.item ( i ) ;

 

            if ( node instanceof RPCElement )

            {

                return(RPCElement)node ;

            }

        }

 

        return null ;

    }

 

    private final MessageElement getChildMessageElement ( MessageElement element )

    {

        NodeList nodeList = element.getChildNodes () ;

 

        if ( nodeList == null )

        {

            return null ;

        }

 

        int count = nodeList.getLength () ;

 

        if ( count == 0 )

        {

            return null ;

        }

 

        for ( int i=0; i < count; i++ )

        {

            Node node = nodeList.item ( i ) ;

 

            if ( node instanceof RPCElement )

            {

                return(MessageElement)node ;

            }

 

            if ( node instanceof SOAPBodyElement )

            {

                return(MessageElement)node ;

            }

 

            if ( node instanceof RPCParam )

            {

                return(MessageElement)node ;

            }

 

            if ( node instanceof MessageElement )

            {

                return(MessageElement)node ;

            }

 

            if ( node instanceof javax.xml.soap.SOAPElement )

            {

                /*

                    インターフェース

                */

            }

        }

 

        return null ;

    }

 

    public final static byte[] readFile ( File file ) throws IOException

    {

        int length = (int)file.length () ;

 

        byte[] content = new byte[length] ;

 

        FileInputStream inputStream = new FileInputStream ( file ) ;

 

        inputStream.read ( content ) ;

 

        inputStream.close () ;

 

        return content ;

    }

}