japan.internet.com
デベロッパー2007年7月17日 10:00
文字サイズ文字サイズ小文字サイズ中文字サイズ大

POJOベースのドメインアプリケーションをWebサービスとして公開する

この記事のURLhttp://japan.internet.com/developer/20070717/27.html
著者:Ramanujam A. Rao
海外internet.com発の記事

はじめに

 エンタープライズアプリケーション開発において結合の緩いサービスが受け入れられるようになったこと、さらにSOA(サービス志向アーキテクチャ)をめぐる以前からの動向を受けて、企業の間では、リモートからの起動と実行が可能なコンシューマブルサービスについての関心が高まっています。またサービスドリブン型アーキテクチャを実現する媒体としてSOAPベースのWebサービスがもつ価値と重要性についても、この数年間で広く認識されるようになりました。

 Webサービスの構築法はさまざまですが、特に企業の場合は、ビジネス機能を実装している既存アプリケーションに既にかなりの投資をしているのが普通です。そのためこうしたケースでは、既存のドメイン機能を安全で簡単かつ効率的な方式でWebサービスとして提供できるデザインが求められています。

 本稿ではAxis2を用いることで、十分なスケーラビリティを維持しつつ、既存のPOJOドリブンJ2EEアプリケーションをWebサービスとして公開する方法について説明します。これらのサービス作成と制御には、現在多くのJ2EEアプリケーションにおいてDI(Dependency Injection:依存性注入)コンテナとして利用されているSpringを利用します。また最後にAxis2エンタープライズWebサービスの配備戦略を解説し、IBM WebSphereなどのアプリケーションサーバに固有の問題についても触れることにします。

アプリケーション

 通常のJ2EEアプリケーションは階層構造を取っており、プレゼンテーション層とビジネス/ドメイン層とが分離しているのが普通です。すべてのコンポーネントを統合するのは、Springなどのフレームワークまたはカスタムファクトリ/コントローラの役割です。本稿では、簡単なWeb層とドメイン層を用いてビジネスロジックをカプセル化するアプリケーションを考えることにします。

 今回のサンプルアプリケーションでは、単純化のためWeb層とドメイン層を共通のプロジェクト構造に統合していますが、本来これらは明確に区別されるものです。図1に、サンプルアプリケーションAccountWebの構成を示します。

図1 既存アプリケーションの構成
図1 既存アプリケーションの構成

 このアプリケーションは、フロントエンドで使われるAccountManagerというドメイン機能を持ちます。AccountManagerはAccountManagerImplとして実装され、ドメインオブジェクトAccountを使用します。ここでも便宜上、ロジックをハードコーディングし、事前定義された各種の入力に基づいた値を返すようにしてあります。実際のアプリケーションであれば、より高度なドメイン/ビジネス層を用意し、データアクセスおよび統合コンポーネントによるデータ入力が行われるはずです。

 ドメインロジックインターフェイスを見ると分かるようにAccountManagerには下記の2つのメソッドが定義されています。

public interface AccountManager {

    public Account getAccount(String accountId);
    public void setStatus(String accountId, Boolean status);
}

 本稿の残りの部分では、Axis2およびSpringを用いてAccountManager機能とその2つのメソッドを公開し、コンシューマブルなWebサービスとして外部から利用させる方法について説明します。

Axis2を用いたWebサービスの構築

 Webサービスを構成するコードのうち、プロバイダサイドのコード部分は「スケルトン」と呼ばれ、コンシューマサイドのコード部分は「スタブ」と呼ばれます。スタブとスケルトンは、マーシャリングおよびアンマーシャリングのリクエストで使用されます。よって、まず目的とするサービスのプロデューササイドのコンポーネントを作成する必要があります。

 Webサービスの構築法には、ボトムアップ形式とトップダウン形式のアプローチがあります。ボトムアップのアプローチでは、最初にJavaクラスを構築しておき、そこからサービス記述子やWSDLを生成します。トップダウン形式のアプローチでは、WSDLを構築しておき、そこからJavaクラスを生成します。今回のサンプルアプリケーションでは、ビジネス機能が既にJavaクラスとして実装されているので、ボトムアップのアプローチを採用します。

 Axis2は同期および非同期サービスをサポートしていますが、今回のサンプルでは同期サービスのみを使用します。Axis2とSpringを用いて既存のドメインクラスからWebサービスを生成するステップを簡単にまとめると次のようになります。

  1. 既存の実装を基にWSDLを生成する。
  2. このWSDLからプロデューササイドのスケルトンおよびクライアントサイドのスタブを生成する。
  3. Springのワイヤリング設定を行い、スケルトン実装を編集して既存クラスにフックする。

 サービスの生成と設定が終わったら、次の作業を行います。

  1. サービスを配備する。
  2. クライアント側からのテストを行う。

 ここから先の手順を実行するには、Axis2バイナリをダウンロードし、アプリケーションクラスパスのライブラリディレクトリにインストールしておく必要があります。WebSphereやWebLogicなど一部のアプリケーションサーバでは、サーバにデフォルトで使われるライブラリとこれらのライブラリが競合する場合があります。この問題については、配備の手順を解説する際に説明します。現段階では、こうした競合はクラスローダおよびその他のクラスパスポリシーを操作することで回避できることを知っておけば十分でしょう。本稿のダウンロードファイルには、すべてのサンプルコードが収録されています。

WSDLの生成

 既存クラスからWSDLを生成するには、Axis2ディストリビューションに用意されているwsdl2javaなどのコマンドライン実行可能バイナリを使用する方法があります。個々のバイナリをスタンドアロンバイナリおよびANTタスクとして使用する方法は、Axis2の付属ドキュメントに詳しく解説されています。Axis2プロジェクトからは、EclipseIntelliJ IDEAMaven 2用のプラグインも提供されています。

 今回のサンプルではEclipseプラグインを使用します。このプラグインは、機能的にはコマンドライン形式のバイナリより劣りますが、Webサービスの生成プロセスを大幅に効率化できるという長所があります。またこのプラグインを用いると、WSDL-to-JavaおよびJava-to-WSDLの両方向の生成をサポートできます。

 柔軟性と分かりやすさのために、生成されたWSDLなどのWebサービス関連のコードを他のプロジェクト内に配置するとよいでしょう。そこで、コンポーネントを生成する前に、IDE内で空のソースとバイナリツリーを含む空のJavaプロジェクトを作成してください。このプロジェクトの名前はAccountWSにします。

 これでEclipseプラグインが使用可能になり、AccountManagerImplクラスを参照してJavaクラスからWSDLを生成できるようになります。変数名の整合性を保つ関係上、必ずインターフェイスではなく実装クラスを参照してください。詳細については、以下、図2の一連のスクリーンショットを参照してください。

図2 EclipseプラグインでJavaクラスからWSDLを生成
図2 EclipseプラグインでJavaクラスからWSDLを生成

 これで、新規の空プロジェクトAccountWS内に「services.wsdl」という名前のファイルが作成されるはずです。このWSDLは、次のように入力/出力の値に応じた2つのサービスを定義しています。

<xs:element name="getAccount">
  <xs:complexType>
   <xs:sequence>
     <xs:element name="accountId" nillable="true" type="xs:string" />
   </xs:sequence>
  </xs:complexType>
</xs:element>
<xs:element name="getAccountResponse">
  <xs:complexType>
   <xs:sequence>
     <xs:element name="return" nillable="true" type="ns0:Account" />
   </xs:sequence>
  </xs:complexType>
</xs:element>
<xs:element name="setStatus">
  <xs:complexType>
    <xs:sequence>
    <xs:element name="accountId" nillable="true" type="xs:string" />
        <xs:element name="status" nillable="true" type="xs:boolean" />
    </xs:sequence>
  </xs:complexType>
</xs:element>

 WSDLが生成されたら、<soap:address>パラメータを手作業で編集し、このサービスで使用するポートおよびURLを指定する必要があります。プラグインによる作成時には、デフォルト値が適用されています。

クライアントおよびサーバサイドコードの生成(スタブおよびスケルトン)

 WSDLの生成が完了したら、次のステップとして、プロデューサおよびコンシューマアプリケーション用のスケルトンおよびスタブをそれぞれ生成します。ここでもEclipseプラグインを使用し、データバインディング用のAxis Data Binding(ADB)オプションを用いてサーバサイドクラスの生成を行います。Axis2およびEclipseプラグインはXMLBeansなど他のデータバインディングもサポートしていますが、今回のサンプルでは単純性からADBを使用します。

 ただしADBには各種の制限が付随します。例えばエンタープライズアプリケーションの構築に使用するには、機能面で力不足と思われます。操作面での柔軟性やスキーマバインディング用の機能を完全に備えたツールが必要な場合は、JiBXなどのXMLバインディングツールの方が適しているかもしれません(Axis2はJiBXをサポートしています)。現状でAxis2プロジェクトからはエンドツーエンドのコード生成ツールは提供されていませんが、JiBXプロジェクトからはそうした処理を比較的簡単にこなせるツールが提供されています。

 以下、図3の一連のスクリーンショットは、プロデューササイドのスケルトンおよびクライアントサイドのスタブの生成ステップをまとめたものです。

図3 Eclipseプラグインを用いたサーバサイドおよびクライアントサイドのコード生成
図3 Eclipseプラグインを用いたサーバサイドおよびクライアントサイドのコード生成

 今回のサンプルでは、スケルトンおよびスタブのディレクトリ構成はそれぞれ図4および図5のようになります。

図4 生成されるサーバサイド(スケルトン)コード
図4 生成されるサーバサイド(スケルトン)コード
図5 生成されるクライアントサイド(スタブ)コード
図5 生成されるクライアントサイド(スタブ)コード

Springとの統合

 各種のJ2EEアプリケーションは、Spring IoCコンテナを使用することで、クラスの起動、依存性管理、インターセプションに関する高度な柔軟性を確保しています。これらの機能は既にアプリケーションの一部になっているので、これをさらに拡張してAxis2ドリブンのWebサービスに取り込みたいところです。これを簡単に行うために、Axis2には、AxisクラスからSpringコンテキストと従属Beanを初期化するためのSpringサポートが用意されています。

 SpringとAxis2を併用するときの基本的な考え方は、Springを利用して、アプリケーションBeanをサービスのAxis2 Message Receiverに注入するというものです。Axis2はSpringアプリケーションのコンテキストサポートを認識し、適切なサービス実装Beanを特定します。そしてメッセージレシーバは、このBeanを用いた実装の委託を行います。こうした処理に関するすべての設定は、サービス配備記述子である「services.xml」の内部で行われます。

 それでは、サンプルの実装クラス用にSpringの「applicationContext.xml」を定義し、Spring対応のサービスクラスを作成してみましょう。Springコンテキストファイルは下記のように変更します。

<beans>
  <!-- Axis2 web service, but to Spring, 
       its just another bean that has dependencies   -->
  <bean id="springAccountservice" 
class="com.corp.account.domain.accountmanager.AccountserviceSkeleton">
    <property name="service" ref="accountManager"/>
  </bean>
  <!-- just another bean/interface with a wired implementation, 
       which is injected by Spring into the web service -->
   <bean id="accountManager" 
         class="com.corp.account.domain.impl.AccountManagerImpl"> 
   </bean>
</beans>

 「accountManager」はPOJO実装クラスを示しており、「springAccountservice」はプロデューササイドのスケルトンをSpringのロードBeanとして定義しています。ここでの目的はこの「springAccountservice」を取得して、サーバメッセージレシーバに認識させることです。そのためには「services.xml」を下記のように編集します。

<parameter name="serviceObjectSupplier" locked="false">
  org.apache.axis2.extensions.spring.receivers.
   SpringServletContextObjectSupplier
</parameter>

<parameter name="SpringBeanName" locked="false">
    springAccountservice
</parameter>

 ここで定義している「serviceObjectSupplier」というパラメータには、Axis2によりオブジェクトサプライヤクラスが入力として与えられます。SpringServletContextObjectSupplierクラスを使用しているのは、Springアプリケーションコンテキストを「web.xml」内でサーブレットコンテキストとして初期化するためです。これは単なる説明上の便宜的な措置です。アプリケーションコンテキストを明示的にロードする必要がある場合は、Axis2からSpringAppContextAwareObjectSupplierクラスが提供されます。「web.xml」内ではSpringコンテキストが次のように設定されています。

<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

 最後に施す変更は、Skeleton実装クラスに関するものです。ここでは実装クラスの注入を行うので、事前ロードされたBeanによるアップデートを行うために、Spring用に空のセッター(setter)メソッドを作成する必要があります。図6は、SpringとAxis2の併用に関する基本的な概念と手順をまとめたものです。

図6 SpringとAxis2の併用
図6 SpringとAxis2の併用

 Springを用いてAxis2 Webサービスを実装するという手法には、いくつかのメリットがあります。POJOベースのビジネス機能実装を拡張してWebサービス呼び出しをサポートすることが簡単にできますし、そうしたアプリケーションに備わった依存性の注入、ワイヤリング、インターセプタを継続して使用することができます。

Webサービスと既存アプリケーションドメインとの統合

 ここまでの手順でWebサービスのプロバイダサイドの構造は用意できたので、次は既存のPOJOドリブンドメイン機能との統合を行います。先に見たように、SpringによるPOJOクラスの注入はSkeletonについて行われます。よって下記のように、そのためのセッターメソッドをスケルトン中に作成する必要があります。

public void setservice(AccountManager service) {
        this.service = service;
}

 このオブジェクトを用いると、ドメインクラス中のメソッドを起動することができます。このドメイン関数はドメインオブジェクトを返すので、これをWebサービスのスキーマオブジェクトにマッピングします。このプロセスをさらに最適化するには、JiBXなどのツールを使ってドメインオブジェクトに直接マッピングします。変更後のサーバサイドコードは次のようになります。

Account acct = service.getAccount(accountId);
    GetAccountResponse response = new GetAccountResponse();
    com.corp.account.domain.bo.xsd.Account acctXSD
     = new com.corp.account.domain.bo.xsd.Account();

    acctXSD.setAccountId(accountId);
    acctXSD.setAddress(acct.getAddress());
    acctXSD.setFirstName(acct.getFirstName());
    acctXSD.setLastName(acct.getLastName());
    acctXSD.setStatus(acct.getStatus());

    response.set_return(acctXSD);

 このコードの最後のステートメントは、サービスレスポンスとしての戻り値を示しています。

サービスの配備

 Axis2の特徴の1つはその配備モデルにあります。Axis2の配備モデルはJ2EE配備のアーカイブベースの構造を踏襲しており、配備およびサービス記述子を包括するアーカイブを使用します。このアーカイブはAxis Application Archive(AAR)と呼ばれています。

 配備するサービスのアーカイブを作成するには、Axis2プロジェクトから提供されている別のEclipseプラグインを使用します。その際に、アーカイブ作成に関するオプションを指定する必要があります。この場合もコマンドラインオプションを使用できます。このアーカイブファイルには、すべてのサービスコードに加えて、サービス記述子として機能する「service.xml」も取り込まれます。基本的な考え方は、このアーカイブをAxis2 Webアプリケーションを通じてアップロードすることで、アプリケーションのホット配備とアップデートを実行時に行うというものです。

 この他に、これらのサービスを既存EARの一部として配備する場合(組み込み型のAxis2配備)のオプションとして、WebプロジェクトにおけるWEB-INFの下層に特殊な「services」ディレクトリを作成し、このディレクトリにアーカイブをドロップするという方法もあります。エンタープライズアプリケーションの多くは管理された環境下で事前に組まれたリリース計画に従って配備されるので、通常は後者のオプションの方が好まれます。後者の場合、アプリケーションの配備EARの中にWebサービスを取り込むことができるからです。この機能を利用すると、管理、所有権、説明責任の取り扱いが簡単化されます。

 なお、このWebプロジェクトのWARは(アプリケーションEAR内の)独立したプロジェクトにすることをお勧めします。他のJSP/Servlet WebアプリケーションのWARと共有するべきではありません。このようにしておくと柔軟性が向上し、またコンテナのWebアプリケーションライブラリとの競合を防止できます。

展開形式での配備アプローチ

 ただし、Springサポートを利用してAARファイルをWebSphereやWebLogicなどのエンタープライズアプリケーションサーバに配備する際には、いくつかの問題があります。よってこれらのサーバについては、展開形式での配備アプローチが推奨されます。下記の手順は、Axis2アプリケーションをWebSphere Application Serverプラットフォームに展開形式で配備するステップをまとめたものです。

  1. AARファイルをWEB-INF下層の専用ディレクトリに展開する。通常は、AARファイル(基本的にはJARファイル)を「WEB-INF/services/<WSDL中のサービス名>」ディレクトリに展開する。ただしSpringサポートを利用して定義されたBeanの実装クラスへの参照を許している場合はプロセスが若干異なり、以降の手順を経る必要がある。
  2. 「WEB-INF/services/<サービス名>」ディレクトリには、サービス構造全体ではなく、「services.xml」およびサービスWSDLのみが格納される。「META-INF」ディレクトリを含めた残りのファイルについては、JAR化してアプリケーションクラスパス中の「WEB-INF/lib」ディレクトリに追加する。これによりSpringは定義されたクラスを検索してそのBean定義をインスタンス化することができる。
  3. 「WEB-INF/」ディレクトリに「service.xml」のコピーを配置する。
  4. Axis2 Webアプリケーションを利用した配備を行わない場合は、配備対象のWebアプリケーションに対して、SOAPサービスまたはRESTサービス宛てのすべてのリクエストを適切なServletにマッピングするための指示を与えなければならない。そのため「WEB-INF/web.xml」についても下記のように変更する必要がある。
  5. <servlet>
      <servlet-name>AxisServlet</servlet-name>
      <servlet-class>
      org.apache.axis2.transport.http.AxisServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
      <servlet-name>AxisRESTServlet</servlet-name>
      <servlet-class>
      org.apache.axis2.transport.http.AxisRESTServlet
      </servlet-class>
      <load-on-startup>2</load-on-startup>
    </servlet>
    
    <servlet-mapping>
      <servlet-name>AxisServlet</servlet-name>
      <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
      <servlet-mapping>
      <servlet-name>AxisRESTServlet</servlet-name>
      <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    
  6. WebSphereに配備すると、WebSphereが持つAxis 1.xベースのWebサービス実装クラスと直接競合することになる。こうした競合は主として「wsdl4j.jar」および「qname.jar」ライブラリで発生する傾向が見られるが、これらに限定されるわけではない。そのためEARとWARの双方に関し、WebSphereクラスローダのポリシーをPARENT_LASTと変更する必要がある。これによりWebSphereは最初にアプリケーションライブラリをロードし、その後にWebSphereの固有ライブラリをロードするようになり、Axis2の配備に関連する問題を回避できる。

動作確認

 アプリケーションの配備と起動が正常に行われたら、次のアドレスにアクセスして動作を確認します。

  • http://localhost:9080/AccountWeb/services/Accountservice?wsdl

 RESTバージョンの場合は、次のアドレスで確認します。

  • http://localhost:9080/AccountWeb/rest/ccountservice/getAccount?accountId=1

 WebLogicの場合も、基本的に同様のプロセスを用います。

サービスのテスト

 サービスの最終的なテストを行うには、コンシューマ側から検証します。REST実装については、ブラウザから直接実行することで簡単に検証できます。図7に、REST起動時の入力および出力を示します。

 アクセス先のURL:

  • http://localhost:9080/AccountWeb/rest/Accountservice/getAccount?accountId=2
図7 RESTベースのサービスの起動とレスポンス
図7 RESTベースのサービスの起動とレスポンス

 ここまで来れば、後は簡単なクライアントを作成することで、SOAP/HTTPを介したサービスの起動テストが行えます。ここでは単純なJavaプロジェクトを作成して、先に生成されたスタブを収めたクライアントjarを取り込みます。実際のアプリケーションでは通常、サービスプロバイダがこれらのファイル(またはコンシューマがスタブやメッセージレシーバの生成に使用するWSDL)を提供します。ここでは説明上の便宜的な措置として、ADBを使用してサービスを起動することにします。複雑なアプリケーションを扱う場合は、JiBXを利用して、Axis2に統合されているスキーマバインディングを行います。Axis2に付属するwsdl2javaというコマンドライン形式のユーティリティは、JiBXクライアントの生成をサポートしています。

 SOAPサービスのテスト用クライアントとして使用するコードを次に示します。

AccountserviceStub stub
   = new AccountserviceStub(
     "http://localhost:9080/AccountWeb/services/Accountservice");
..
AccountserviceStub.GetAccount req
   = new AccountserviceStub.GetAccount();
req.setAccountId(accountId);
AccountserviceStub.GetAccountResponse res = stub.getAccount(req);

name = res.get_return().getFirstName()
     + " "
     + res.get_return().getLastName();

 このクラスを実行してクライアントとサーバの間で交わされるTCP/IPトラフィックを監視すると、呼び出しが正常に行われた場合に、次のような情報が交換されることが確認できるはずです。これらの呼び出しはgetAccountメソッドに対するもので、パラメータaccountIdの値が2であるすべてのメソッドについて実施されています。

リクエスト
<?xml version="1.0" 
      encoding="http://www.w3.org/2003/05/soap-envelope"?>
  <soapenv:Envelope 
      xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
    <soapenv:Header/>
    <soapenv:Body>
      <ns2:getAccount
       xmlns:ns2="http://AccountManager.domain.account.corp.com/types">
          <ns2:accountId>2</ns2:accountId>
      </ns2:getAccount>
    </soapenv:Body>
  </soapenv:Envelope>
レスポンス
<?xml version="1.0"
   encoding="http://www.w3.org/2003/05/soap-envelope"?>
  <soapenv:Envelope
     xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
    <soapenv:Header/>
    <soapenv:Body>
      <ns2:getAccountResponse
       xmlns:ns2="http://AccountManager.domain.account.corp.com/types">
        <ns2:return>
            <ns6:accountId
              xmlns:ns6="http://bo.domain.account.corp.com/xsd">
          2
          </ns6:accountId>
          <ns7:address 
            xmlns:ns7="http://bo.domain.account.corp.com/xsd">
          2222, Lincoln Av, New York
          </ns7:address>
          <ns8:firstName 
            xmlns:ns8="http://bo.domain.account.corp.com/xsd">
          Jane
          </ns8:firstName>
          <ns9:lastName 
            xmlns:ns9="http://bo.domain.account.corp.com/xsd">
          Smith
          </ns9:lastName>
          <ns10:status 
             xmlns:ns10="http://bo.domain.account.corp.com/xsd">
          false
          </ns10:status>
        </ns2:return>
      </ns2:getAccountResponse>
    </soapenv:Body>
  </soapenv:Envelope>

将来的な展望

 本稿では、既存ドメインに基づいてWebサービスを作成する基本的な方法を紹介しました。Webサービスを用いたより実用的なエンタープライズアプリケーションを構築する場合は、セキュリティやメッセージングの信頼性など、より複雑な問題に対処する必要があります。Axis2のアーキテクチャを利用すると、これらの機能を比較的簡単に、モジュール化された方法で実装できるというメリットがあります。このプロセスは大雑把に言えば、サービス記述子を編集して必要なモジュールへの参照を追加し、それぞれのポリシーを設定するという流れになります。

 本稿では、J2EEアプリケーション内の既存のPOJOベースのドメイン機能を公開するための簡単な代替手段としてAxis2を紹介しました。このような形でAxis2を利用すると、これまでアプリケーションアーキテクチャに行ってきた投資を無駄にせず、コードの書き直しを最小限に抑えた上で、既存のPOJOベースのドメインアプリケーションをリモートから利用できる堅牢なWebサービスとして公開することができます。

著者紹介

Ramanujam A. Rao(Ramanujam A. Rao)
ソフトウェア設計者兼エンジニアで、エンタープライズアプリケーションの設計と配備を専門とする。現在は、エンタープライズアプリケーションアーキテクチャの分野におけるコンサルティングおよび、J2EEプラットフォームを用いたスケーラブルな分散型アプリケーションの構築に関するサポートを行っている。連絡先はarrao@acm.org
japan.internet.comのウエブサイトの内容は全て、国際法、日本国内法の定める著作権法並びに商標法の規定によって保護されており、その知的財産権、著作権、商標の所有者はインターネットコム株式会社、インターネットコム株式会社の関連会社または第三者にあたる権利者となっています。
本サイトの全てのコンテンツ、テキスト、グラフィック、写真、表、グラフ、音声、動画などに関して、その一部または全部を、japan.internet.comの許諾なしに、変更、複製、再出版、アップロード、掲示、転送、配布、さらには、社内LAN、メーリングリストなどにおいて共有することはできません。
ただし、コンテンツの著作権又は所有権情報を変更あるいは削除せず、利用者自身の個人的かつ非商業的な利用目的に限ってのみ、本サイトのコンテンツをプリント、ダウンロードすることは認められています。

Copyright 2012 internet.com K.K. (Japan) All Rights Reserved.