Page History
SOAP Agentメッセージ・ハンドラー・フレームワークはAxisメッセージ・ハンドラー・フレームワークの制限をなくすために開発されたもので、要求ハンドラーや応答ハンドラーを追加する場合にお勧めの方法です。
Apache Axisメッセージ・ハンドラー・フレームワーク用に開発されたメッセージ・ハンドラーは、SOAP Agentメッセージ・ハンドラー・フレームワークで使用できます。
特定のSOAP Agentサービスにメッセージ・ハンドラーを追加するには、SOAPAgentService.propertiesファイルに'service.handlers.サービス名' エントリーを追加します。
SOAP AgentコマンドOPEN SERVICE (サービス名)が実行されると、実行するプログラムにサービス・クラスとメッセージ・ハンドラー・ファイルが割り当てられます。
service.test=com.acme.service.soap.TestServiceservice.handlers.test=handlers/soapagent-handlers.xml
複数のエージェント・サービス構成を1つのファイルに含めることができます。
要求ハンドラーや応答ハンドラーの追加はオプションです。
複数のハンドラー要素を含めることで簡単なメッセージ・ハンドラー・チェーンを作成できます。
要求メッセージ・ハンドラーと応答メッセージ・ハンドラーは、すべてのサービス操作または1つの特定の操作に割り当てることができます。
各ハンドラー要素はゼロ個以上のパラメータ要素で構成できます。
これらのパラメータ要素がインスタンス化され、インスタンス化されたハンドラー・クラスに渡されます。
パラメータ値の属性に中括弧で囲まれた値がある場合、その値はLANSAフィールド名と仮定され、LANSAフィールドの値がハンドラーに渡されます。LANSAフィールドをハンドラー・クラスで使用できるようにするには、CALLコマンドでSERVICE_EXCHANGE(*FIELD)キーワードを使用します。
メッセージ・ハンドラー構成
<?xml version="1.0" encoding="utf-8"?> <services> <!-- Assign SOAPHeaderHandler to all operations in the Test service --><service name="test"> <request> <handler class="com.acme.axis.handler.SOAPHeaderHandler"/> </request> <response> <handler class="com.acme.axis.handler.SOAPHeaderHandler"/> </response> </service> <!-- Assign SecurityHandler and SOAPHeaderHandler to the Test service login operation --><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 ( 文字列名, オブジェクト値 ) MessageContext - Object value getProperty ( 文字列名 ) */ } 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[] コンテンツでフォーム変換が発生するリスク有り */ 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[] メモリー内にシリアライズ、 もしくは、文字列を作成し、コンテンツの引数として使用なども可能。 */ 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[] メモリー内にシリアライズ、 もしくは、文字列を作成し、コンテンツの引数として使用なども可能。 */ 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 エレメントを文字列に、パーサーをドキュメントに変換 */ 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 ; }} |