- PR -

AXIS DIMEによる添付ファイルの送信

1
投稿者投稿内容
タカチ
会議室デビュー日: 2004/08/04
投稿数: 12
投稿日時: 2004-08-09 11:25
お世話になります。
現在、SOAPでDIMEによる添付ファイルの送信テスト行っているのですが、
うまくいかず悩んでいます。

作成したテストモジュールを実行すると書きのエラーが出てしまいます。

##### エラー ######
- Mapping Exception to AxisFault
AxisFault
faultCode: {http://xml.apache.org/axis/}Server.userException
faultString: org.xml.sax.SAXException: No such operation 'PutData'
faultActor: null
faultDetail:

本エラーにつきまして、どなたかご存知な方いらっしゃいましたら
アドバイスを頂けないでしょうか。
また、DIMEによる添付ファイルの送信(受信)につきまして
よいサンプル等ありましたら、ご紹介頂けないでしょうか。
宜しくお願いいたします。

以下、環境とソースです。

クライアント:Apache Axis
サーバ:Apache Axis
OS:Windows XP

以下、ソースです。

##### サーバ側 ######
import java.io.FileOutputStream;
import java.io.IOException;
import javax.xml.soap.SOAPException;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.attachments.AttachmentPart;

public class DimeService {
public String PutData(String originalName) throws SOAPException {
try {
MessageContext ctx = MessageContext.getCurrentContext();
Message msg = ctx.getRequestMessage();
AttachmentPart part = (AttachmentPart)msg.getAttachments().next();

FileOutputStream fs = new FileOutputStream("C:\\files\\" + originalName);
part.getDataHandler().writeTo(fs);
fs.close();

return "OK";
} catch (IOException ioex) {
ioex.printStackTrace();
throw new SOAPException("error", ioex);
}
}
}

##### クライアント側 ######
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.ser.JAFDataHandlerDeserializerFactory;
import org.apache.axis.encoding.ser.JAFDataHandlerSerializerFactory;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.xml.rpc.ParameterMode;
import javax.xml.namespace.QName;
import java.net.URL;

public class DimeClientTest {

public static void main(String[] args) throws Exception {

String fileName = args[0];
DataHandler dhSource = new DataHandler(new FileDataSource(fileName));
Service service = new Service();

Call call = (Call)service.createCall();

call.setTargetEndpointAddress(new URL(args[1]));

call.setOperationStyle("wrapped");

call.setOperationName(new QName("DimeService", "PutData"));
// call.setReturnQName(new QName("http://tempuri.org/", "PutDataResult"));
call.setReturnType(new QName("http://www.w3.org/2001/XMLSchema", "string"), String.class);
call.setUseSOAPAction(true);
// call.setSOAPActionURI("http://tempuri.org/PutData");
call.setEncodingStyle(null);
call.setScopedProperty(org.apache.axis.client.Call.SEND_TYPE_ATTR, Boolean.FALSE);
call.setScopedProperty( org.apache.axis.AxisEngine.PROP_DOMULTIREFS, Boolean.FALSE);

QName att = new QName("DimeService", "DataHandler");

call.registerTypeMapping(dhSource.getClass(),
att, JAFDataHandlerSerializerFactory.class,
JAFDataHandlerDeserializerFactory.class);

call.addParameter(new QName("http://tempuri.org/", "originalName"),
new QName("http://www.w3.org/2001/XMLSchema", "string"),
String.class, ParameterMode.IN);

call.addParameter("data", att, ParameterMode.IN);

call.setProperty(Call.ATTACHMENT_ENCAPSULATION_FORMAT,
Call.ATTACHMENT_ENCAPSULATION_FORMAT_DIME);

Object ret = call.invoke(new Object[]
{ new java.io.File(fileName).getName(), dhSource } );
}
}

##### WSDDファイル ######
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="urn:DimeService" provider="java:RPC">
<parameter name="className" value="server.api.DimeService"/>
<parameter name="allowedMethods" value="*"/>
</service>
</deployment>


上記のソースをコンパイルして、

java DimeClientTest <ファイルパス> http://localhost:8080/axis/services/urn%3ADimeService
SJ0392
ベテラン
会議室デビュー日: 2004/02/05
投稿数: 62
お住まい・勤務地: 神奈川・横浜
投稿日時: 2004-08-11 13:00
クライアントプログラムを実行する際のCLASSPATHに、mail.jarは含まれますか?
%CATALINA_HOME%(旧称:TOMCAT_HOME)\common\lib 配下にあるはずです。

逆質問ですが、AXISにWebサービスとして登録されてますか?
通常「java org.apache.axis.wsdl.WSDL2Java http://localhost:8080/axis/services/DimeService?wsdl」とすればクライアントプログラムの大半は自動生成されます。
まぁ細かい事は「http://muimi.com/j/axis/」を参照下さい。
私は最初に上記サイトを参考にしたので、タカチさんのプログラムの方が見慣れてません。

# 参考までに CLASSPATH や tomcat、javaのバージョンがあると他の方も回答しやすいかも。
SJ0392
ベテラン
会議室デビュー日: 2004/02/05
投稿数: 62
お住まい・勤務地: 神奈川・横浜
投稿日時: 2004-08-11 13:53
補足:後で閲覧した人が「mail.jar が必要なのは何故?」と疑問にもたれるとアレなので。
下記は経験から書くもので実際は不明です。

クライアントがAXISにアクセスすると私の環境では下記のようなデータが送信されます。
見てもらえば判ると思いますが MIME で区切られています。
つまりMIME形式対応にしたいがためだけに、mail.jar が必要という罠。
私は4日もハマリました。

コード:
POST / HTTP/1.0
Content-Type: multipart/related; type="text/xml"; start="<C9C08CB7DD03D41F0FAB66
58BA2A14EF>";   boundary="----=_Part_0_15055830.1092198178244"
Accept: application/soap+xml, application/dime, multipart/related, text/*
User-Agent: Axis/1.1
Host: 秘密
Cache-Control: no-cache
Pragma: no-cache
SOAPAction: ""
Content-Length: 3967


------=_Part_0_15055830.1092198178244
Content-Type: text/xml; charset=UTF-8
Content-Transfer-Encoding: binary
Content-Id: <C9C08CB7DD03D41F0FAB6658BA2A14EF>

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope ...省略>
 <soapenv:Body>
   ...中略
 </soapenv:Body>
</soapenv:Envelope>
------=_Part_0_15055830.1092198178244
Content-Type: text/plain
Content-Transfer-Encoding: binary
Content-Id: <281C14979AD28DB6994F314B7E2B7865>

...ここにファイル内容
------=_Part_0_15055830.1092198178244--

タカチ
会議室デビュー日: 2004/08/04
投稿数: 12
投稿日時: 2004-08-11 22:16
お世話になります。
SJ0392さん、ご返信ありがとうございます。
以下、コメント頂いた内容について回答いたします。

引用---------------------------------------------------
クライアントプログラムを実行する際のCLASSPATHに、
mail.jarは含まれますか? %CATALINA_HOME%(旧称:TOMCAT_
HOME)\common\lib 配下にあるはずです。
-------------------------------------------------------
【回答】
クラスの実行に関しては、下記のBATファイルを起動して行って
おります。
クラスパスに mail.jar も含めています。

ここから---→
set PATH=c:\jdk1.3.1_10\bin;c:\apache-ant-1.6.2\bin;%PATH%
set AXIS_HOME=c:\axis-1_1
set AXIS_LIB=%AXIS_HOME%\lib
set TOMCAT_HOME=C:\Program Files\Apache Tomcat 4.0
set TOMCAT_LIB=%TOMCAT_HOME%\lib
set TOMCAT_COMMON_LIB=%TOMCAT_HOME%\common\lib

---以下、実際は一行---
set CLASSPATH=.;
%AXIS_LIB%\axis.jar;
%AXIS_LIB%\jaxrpc.jar;
%AXIS_LIB%\saaj.jar;
%AXIS_LIB%\commons-logging.jar;
%AXIS_LIB%\commons-discovery.jar;
%AXIS_LIB%\commons-discovery.jar;
%AXIS_LIB%\jaxrpc.jar;
%AXIS_LIB%\log4j-1.2.8.jar;
%AXIS_LIB%\wsdl4j.jar;
%AXIS_LIB%\xerces.jar;
%AXIS_LIB%\axis-ant.jar;
%TOMCAT_COMMON_LIB%\activation.jar;
%TOMCAT_COMMON_LIB%\jaxrpc.jar;
%TOMCAT_COMMON_LIB%\jdbc2_0-stdext.jar;
%TOMCAT_COMMON_LIB%\jndi.jar;
%TOMCAT_COMMON_LIB%\jta-spec1_0_1.jar;
%TOMCAT_COMMON_LIB%\mail.jar;
%TOMCAT_COMMON_LIB%\naming-common.jar;
%TOMCAT_COMMON_LIB%\naming-resources.jar;
%TOMCAT_COMMON_LIB%\saaj.jar;
%TOMCAT_COMMON_LIB%\servlet.jar;
%TOMCAT_COMMON_LIB%\tools.jar;
%TOMCAT_COMMON_LIB%\tyrex-0.9.7.0.jar;
%TOMCAT_COMMON_LIB%\xerces.jar;
%CLASSPATH%
←---ここまで

引用---------------------------------------------------
逆質問ですが、AXISにWebサービスとして登録されてますか?
通常「java org.apache.axis.wsdl.WSDL2Java http://local
host:8080/axis/services/DimeService?wsdl」とすればクライ
アントプログラムの大半は自動生成されます。
まぁ細かい事は「http://muimi.com/j/axis/」を参照下さい。
私は最初に上記サイトを参考にしたので、タカチさんのプロ
グラムの方が見慣れてません。
-------------------------------------------------------
【回答】
WSDL2Javaからクライアントプログラムの生成を行っている
かということをおっしゃっているのですよね?
それであれば試してみました。
ただ、初回の投稿に添付したサーバプログラムをデプロイし、
WSDLからクライアントプログラムを自動生成しても、添付に
関するロジックがごっそり抜けてしまっているような気がし
ます。

ちなみに、サーバプログラムの作成については下記を参考にしました。
http://www.atmarkit.co.jp/fdotnet/special/wse04/wse04_04.html

ただ、参考としたプログラムは、.NET(クライアント)⇔AXIS(サーバ)
の構成でしたので、AXIS(クライアント)⇔AXIS(サーバ)を意識した内容
に書き直しました。

引用---------------------------------------------------
# 参考までに CLASSPATH や tomcat、javaのバージョンがあ
ると他の方も回答しやすいかも。
-------------------------------------------------------
【回答】
おっしゃる通りです。(-_-
以下、バージョンです。

Tomcat:jakarta-tomcat-4.0.6
Java :j2sdk-1_3_1_10
Axis :Version1.1
OS :Windows XP

以上です。
SJ0392
ベテラン
会議室デビュー日: 2004/02/05
投稿数: 62
お住まい・勤務地: 神奈川・横浜
投稿日時: 2004-08-12 20:22
これ以上は私の実力では回答できません。
タカチさんに「方向転換しろ」という訳ではありませんが私はコレで出来ましたという一例。
詳細に書くと大変なので要所だけ。(ってゆーか1つの記事に近い気もする)
ちなみに linux で作成しているのでパスなどは適当に読み替えてください。
環境は OS:Linux / JAVA:1.4.1 / TOMCAT:4.1.30 / AXIS:1.1 です。

(1)下記ファイルを作成しコンパイル
コード:
public interface xo extends java.rmi.Remote {
   public String sendFile(String orgName, javax.activation.DataHandler attach) throws java.rmi.RemoteException;
}



(2)WSDLファイルを作成
java org.apache.axis.wsdl.Java2WSDL -o xo.wsdl -l"http://localhost/axis/services/xo" -n "urn:xo" -p"xo" "urn:xo" xo

(3)WSDLファイルからJavaプログラム生成
java org.apache.axis.wsdl.WSDL2Java -o . -s -Nurl:xo xo xo.wsdl

(4)「xo_pkg」という生成されたディレクトリにある XoSoapBindingImpl.java を編集し同ディレクトリに全ファイルをコンパイル。
deploy.wsdd の in0 を orgName に置換。
コード:
package xo_pkg;

import java.io.FileOutputStream;

public class XoSoapBindingImpl implements xo_pkg.Xo{
    public java.lang.String sendFile(java.lang.String orgName, javax.activation.DataHandler in1) throws java.rmi.Remo
teException {
        try{
                FileOutputStream fs = new FileOutputStream("/usr/local/" + orgName);
                in1.writeTo(fs);
                fs.close();
                return "ok";
        }catch(Exception ex){
                return "ng:"+ex.toString();
        }
    }
}


javac *.java

(5)AXISディレクトリに xo_pkg を作成し、Xo.class と XoSoapBindingImpl.class をコピー
$TOMCAT_HOME/webapps/axis/WEB-INF/classes/xo_pkg

(6)サービスを登録(TOMCATのポート(def:8080)を使用不可にしているとエラーになります)
java org.apache.axis.client.AdminClient deploy.wsdd

(7)xo.java を作成したディレクトリにクライアントプログラム作成しコンパイル。
作成されたクラスを実行すると、"ok"が返ってきて、/usr/local/xo.java が作成されている。
コード:
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.activation.FileTypeMap;
import xo_pkg.*;

public class XoClient{
public static void main (String[] args) throws Exception {
        try{
                String file = "/tmp/xo.java";  // 実在するファイル
                FileDataSource fds = new FileDataSource(file);
                fds.setFileTypeMap(FileTypeMap.getDefaultFileTypeMap());
                DataHandler dh = new DataHandler(fds);

                Xo service = new XoServiceLocator().getxo();
                String ret = ((XoSoapBindingStub)service).sendMessage("xo.java",dh);
                System.out.println(" ret = "+ ret +"_end");
        }catch(Exception ex){
                ex.printStackTrace();
        }
}
}


javac XoClient.java
java XoClient
タカチ
会議室デビュー日: 2004/08/04
投稿数: 12
投稿日時: 2004-08-16 12:02
お世話になります。
SJ0392さん、ご返信ありがとうございます。

大変参考になるサンプルありがとうございます。
本当、1つの記事ですね(笑)

頂いたサンプルは添付ファイルをサーバに送信するものでしたので、
逆に、サーバから添付ファイルを受信するプログラムを作成してみました。

・戻り値として、複合型を持つサーバ側プログラム(インターフェース)を作成
・戻り値の複合型クラス作成(要素としてDataHandlerを持つ)
・java2WSDLで、サーバ側プログラム(メソッド)からWSDLを自動作成
・WSDL2Javaでスタブ、スケルトン、wsddファイルを自動生成
・スケルトンをサーバに配置してデプロイ
・スタブを利用するスケルトンクラスを作成、そして動作確認・・・

見事、添付ファイルを含んだ複合型データを受信することが出来ました(泣)

ただ、気になることが一つあります。
SOAPの特徴として、『多言語との相互運用』というものがありますが、
今回のWSDLを利用して、.NETでクライアントプログラムを作成しようと
した場合どうなるかです。

おそらく、WSDLの<types>要素に、「DataHandler」というJAVA特有の型
が記述されてしまっている以上やっぱり難しいのでしょうか・・・?

試してみたいと思っています。
・WSDLのMIME拡張(DIME拡張)という言葉が浮かび上がってくるような気
 がします・・・。
#これはこれでまたまた報告させて頂きたいと思っています。

どうもありがとうございました。
今後とも宜しくお願いいたします。


1

スキルアップ/キャリアアップ(JOB@IT)