- PR -

apache soap と .net での webservice実現方法について

1
投稿者投稿内容
やすみん
会議室デビュー日: 2003/03/31
投稿数: 4
投稿日時: 2003-03-31 19:08
はじめまして

現在apache soap2.2(サーバ)で作成されているwebサービスに
.net環境(.net framework使用)から 接続を試みているのですが
うまくいきません。

ResponseのSOAPメッセージを見てみると、
apache soap側がオブジェクト配列を返しており、
タイプがxsd:ur-type[](apacheの方は1999スキーマ使ってるから)
となっています。
そのため .netの方で解釈できないのが原因のようです。

サーバ側はもう作成されているので、変更できないのですが、
クライアント側で何とかなる方法はありませんか

何分、初心者なもので、質問内容が良くわからない箇所があると思いますが、
ご教授のほどよろしくお願いいたします。
NothingButXMLInfoSet
ベテラン
会議室デビュー日: 2003/03/31
投稿数: 65
投稿日時: 2003-03-31 20:19
Apache SOAPのバージョンを2.3以上にあげるのは不可能ですか?いまさら古いバージョンにあわせて新しいものを作る労力は惜しいと思いますが。。。今後ますますInteropできなくなっていくのは確実ですし、Interopを視野に入れないのならSOAP/Webサービスを使う理由がありませんから。。。
やすみん
会議室デビュー日: 2003/03/31
投稿数: 4
投稿日時: 2003-04-01 09:44
早々のご回答ありがとうございます。

apache soap 2.3にすると可能だということは、2001 XML Schema対応になっているということですか?

バージョンUPの件なのですが、サーバ側は既に作成済みでなので、クライアント側で何とか対応しなければならないのです。
私もサーバ側でVUPや、カスタム(デ)シリアライザーの作成で対応という意見には賛成なのですが。。。

というわけで、クライアント側で対処する何か良い方法はございませんか?

もし、.net環境で実現できないとなると、クライアント側もapache soap2.2か
ms soop toolkit で作成しなければと考えておりまが、
なにぶん初心者なもので、本当にできないのか判断がつかない状況です。

可能か不可能かだけでもよろしいので、アドバイスをよろしくお願いいたします。
NothingButXMLInfoSet
ベテラン
会議室デビュー日: 2003/03/31
投稿数: 65
投稿日時: 2003-04-01 10:02
引用:
apache soap 2.3にすると可能だということは、2001 XML Schema対応になっているということですか?


シリアライザのデフォルトの出力が2001スキーマになっていると理解しています。2.2も2001スキーマに対応していたと思いますが。

引用:
バージョンUPの件なのですが、サーバ側は既に作成済みでなので、


アプリケーション(Javaクラス)はそのままで、インフラ(Apache SOAP)だけをバージョンアップすることも許可されないのでしょうか?2.2から2.3への以降にはバグ修正という意味もありますが。http://ws.apache.org/soap/releases.html

引用:
もし、.net環境で実現できないとなると、クライアント側もapache soap2.2かms soop toolkit で作成しなければと考えておりまが、


いえ、しょせんはXMLですから、コードを書いて1999スキーマに対応することも不可能ではありません。自分で書かなければならないということです。これは1999スキーマを使う限りはどのツールキットを使っても同じです。手間もどれでも同じでしょう。

アプリケーションではなくインフラのバージョンアップということなので、まだ検討の余地があると思うのですが。もちろんテスト工数がかかりますけれども。
やすみん
会議室デビュー日: 2003/03/31
投稿数: 4
投稿日時: 2003-04-01 13:59
たびたびのご回答誠にありがとうございます。

ご指摘のとおりに、最終的にはインフラのVUPも考えようと思いますが、
できることなら現状の状態で何とかできないかと思っております。

もしよろしければ .net framework を使用し1999スキーマ(xsd:ur-type)に対応したプロキシを作成する方法を教えていただけないでしょうか?
ヒント程度でもよろしいので宜しくお願いいたします。

以下参考-----------------------------------------------------
現状サーバ側はobject[2]を返すようになっていて

レスポンスsopeメッセージは以下のようになっております。
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/1999/XMLSchema">
<SOAP-ENV:Body>
<ns1:eResponse xmlns:ns1="urn:test"
SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<return xmlns:ns2="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Array"
ns2:arrayType="xsd:ur-type[2]">
<item xsi:type="xsd:string">0</item>
<item xsi:type="ns2:Array" ns2:arrayType="xsd:ur-type[2]">
<item xsi:type="ns2:Array" ns2:arrayType="xsd:ur-type[2]">
<item xsi:type="xsd:string">XXXX</item>
<item xsi:type="xsd:long">0</item>

</item>
<item xsi:type="ns2:Array" ns2:arrayType="xsd:ur-type[2]">
<item xsi:type="xsd:string">XXXX</item>
<item xsi:type="xsd:long">1</item>
</item>
</item>
</return>
</ns1:eResponse>

ちなみにクライアント側では以下のようなエラーが出ている状態です。

ハンドルされていない例外 : System.InvalidOperationException: XML ドキュメント (5
,2) でエラーが発生しました。 ---> System.InvalidOperationException: 指定された型
は認識されませんでした : name='ur-type'、namespace='http://www.w3.org/1999/XMLSc
hema'、場所 <return xmlns=''>
NothingButXMLInfoSet
ベテラン
会議室デビュー日: 2003/03/31
投稿数: 65
投稿日時: 2003-04-01 16:00
SoapExtensionでur-typeをanyTypeに強制変換してみました。力技ですが、Web参照を活かすにはこれがいいかなと思います。やすみんさんが添付されたSOAPメッセージは通りました。

コード:
using System;
using System.IO;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Text;

namespace fumiakiy {
  public class Evoxtension : SoapExtension {
    private Stream instr, outstr;
    public override Stream ChainStream(Stream stream) {
      outstr = stream;
      instr = new MemoryStream();
      return instr;
    }
  
    public override object GetInitializer(Type serviceType)  { return null; }
    public override object GetInitializer(
        LogicalMethodInfo methodInfo, 
        SoapExtensionAttribute attribute) { return null; }
    public override void Initialize(object initializer) {}
  
    public override void ProcessMessage(SoapMessage message) {
      StreamReader r;
      StreamWriter w;
      StringBuilder sb;
      switch(message.Stage) {
        case SoapMessageStage.BeforeDeserialize:
          r = new StreamReader(outstr);
          w = new StreamWriter(instr);
          sb = new StringBuilder(r.ReadToEnd());
          sb.Replace("1999", "2001");
          sb.Replace("ur-type", "anyType");
          w.Write(sb.ToString());
          w.Flush();
          instr.Position = 0;
          break;
        case SoapMessageStage.AfterSerialize:
          r = new StreamReader(instr);
          w = new StreamWriter(outstr);
          sb = new StringBuilder(r.ReadToEnd());
          sb.Replace("2001", "1999");
          sb.Replace("anyType", "ur-type");
          w.Write(sb.ToString());
          w.Flush();
          instr.Position = 0;
          break;
        default:
          break;
      }
    }
  }

  [AttributeUsage(AttributeTargets.Method)]
  public class EvoxtensionAttribute : SoapExtensionAttribute {
    private int priority;
    public override Type ExtensionType {
      get { return typeof(Evoxtension); }
    }
    public override int Priority {
      get { return priority; }
      set { priority = value; }
    }
  }
}


まずこれをクライアントのEXEに含むか、またはDLLにします。そして、Web参照(WSDL.EXE)で作成されたメソッドに以下のように属性を指定します。

コード:
[System.Web.Services.Protocols.SoapRpcMethodAttribute(
    "urn:hoge/e", RequestNamespace="urn:hoge", 
    ResponseNamespace="urn:hoge")]
[fumiakiy.Evoxtension()]
public object[] e() {
  object[] results = this.Invoke("e", new object[0]);
  return ((object[])(results[0]));
}


であとは普通にプロキシ経由でメソッド呼び出しをします。
やすみん
会議室デビュー日: 2003/03/31
投稿数: 4
投稿日時: 2003-04-03 11:19
NothingButXMLInfoSet さん
度々のご回答誠にありがとうございます。

提示していただいたサンプルを元に拡張機能を作成したところ
うまくいきました。
本当に勉強になりましたし、助かりました。

感謝感謝です。
1

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