ColdFusion で CFC が検索されるアプリケーションパスまたはルートフォルダーを参照して選択します。
<cfcomponent rest="true" restpath="restService"> <cffunction name="sayHello" access="remote" returntype="String" httpmethod="GET"> <cfset rest = "Hello World"> <cfreturn rest> </cffunction> </cfcomponent>
REST サービスを使用するアプリケーションの登録
ColdFusion 10 では、REST(Representational State Transfer)サービスを作成して公開できます。クライアントは、HTTP/HTTPS リクエストを使用してこのサービスを使用できます。
REST とは
REST に関する概念情報を提供する Java Tutorial については、次の URL にアクセスしてください。
http://download.oracle.com/javaee/6/tutorial/doc/gijqy.html
REST と ColdFusion
タグ( cfcomponent 、 cffuntion 、 cfargument )内の特定の属性を定義することによって REST リソースとして公開できます。
- *HTTP のリクエストレスポンスモデルを順守:HTTP を媒体として使用するだけでなく、サービスでは HTTP のすべての基準に従うことができます。REST サービスとして公開されたコンポーネントは、HTTP/HTTPS リクエストを使用して利用できます。REST サービスは URI(Uniform Resource Identifier)によって識別され、Web ページからだけでなく、ブラウザーのアドレスバーで URI を指定してアクセスできます。
- すべての HTTP メソッドをサポート: REST 対応 CFC は、HTTP メソッドの GET、POST、PUT、DELETE、HEAD および OPTIONS をサポートします。
- シリアル化/シリアル化解除の暗黙の処理:ColdFusion は JSON および XML のシリアル化/シリアル化解除をネイティブにサポートします。したがって、クライアントアプリケーションは HTTP/HTTPS リクエストを発行することによって REST サービスを使用できます。レスポンスは XML または JSON 形式にシリアル化できます。
- Web サービスを REST サービスおよび WSDL サービスの双方で公開:同じ ColdFusion コンポーネントを REST サービスおよび WSDL サービスとして作成し、公開できます。
REST Web サービスの作成
- ColdFusion コンポーネントまたはコンポーネント内の関数を REST リソースとして作成し公開できます。
- CFC を REST Web サービスとして作成するには、cfcomponent タグで restPath または rest を指定します。
- cffunction で、REST リソースとして公開する関数の access 属性を remote に設定します。
例
REST 対応にする CFC を作成した後、restInitAplication 関数を使用して、または ColdFusion Administrator で、Web サービスとして登録するためのフォルダーを指定します。
ネストされた REST アプリケーションは登録できません。
ColdFusion Administrator の使用(データとサービス/REST サービス)
フォルダーを指定する際に、rest または restPath を指定したフォルダーまたはサブフォルダーにあるすべての CFC が登録されます。
-
-
(オプション)「サービスマッピング」セクションで、アプリケーション名の代わりに仮想マッピングを指定します。フォルダーに Application.cfc がありアプリケーション名が指定されている場合、サービスは、アプリケーション名で識別されます。サービスマッピングを指定すれば、これを上書きできます。この場合、指定されたサービスマッピングでサービスが識別されます。フォルダーに Applicaiton.cfc がない場合、サービスマッピングの指定は必須です。ColdFusion ルートの外部に REST フォルダーを指定することを選択する場合、次のマッピングのどちらかを追加してフォルダーを登録します。c:\restfolder のマッピングを \map として追加したと見なします。
<cfset restinit("c:\restfolder","myapp")> <cfset restinit("\map","myapp")>
-
(オプション)デフォルト REST サービスとしてアプリケーションを指定します。1 つのサーバーインスタンスに対してデフォルトとして設定できるアプリケーションは 1 つだけです。デフォルトアプリケーションはいつでも変更できます。「デフォルトアプリケーションを設定する」を選択し、「サービスを追加」をクリックします。デフォルトとしてのサービスを削除するには、選択を解除します。
-
詳細を指定したら、「サービスを追加」をクリックして登録します。「アクティブな ColdFusion REST サービス」セクションで、登録したすべての Web サービスの詳細を指定します。
登録が済むと、すべての CFC は RESTful サービスとして公開されます。登録後に起動すると、登録されたサービスが自動的に公開されます。注意:アプリケーションの REST 関連コンポーネントを変更したときは常に、アプリケーションを更新します。
Web サービスへのアクセス
- 以下の例に示すように、We サービスにアクセスするには cfhttpto タグを使用します。
<cfhttp url="http://localhost:8500/rest/RestTest/restService" method="get" port="8500" result="res"> </cfhttp>
- ブラウザーで URL http://localhost:8500/rest/RestTest/restService を指定してアクセスします。
URL の解釈
例で指定した URL は次のように解釈できます。
URL のコンポーネント |
説明 |
---|---|
http://localhost:8500 |
ColdFusion サーバーの IP アドレスとポートを含むベース URL です。ColdFusion を JEE アプリケーションとしてデプロイする場合、URL にはコンテキストルートが含まれます。例: http://localhost:8500*/cfusion* 。 |
rest |
送信されるリクエストが REST リクエストであることを示します。このデフォルト値の名前を変更するには、cfusion/wwroot/WEB-INF で利用可能な web.xml と、uriworkermap のプロパティファイルが同じマッピングに更新されました。 |
restTest |
ColdFusion Administrator でサービスを登録するときに使用したアプリケーション名またはサービスマッピングです。ColdFusion Administrator でサービスマッピングを指定していない場合、アプリケーション名は Application.cfc から取得されます。 |
restService |
サービスで定義した REST パスです。つまり、cfcomponent タグの属性 restPath の値です。 |
accept ヘッダーの提供
accept ヘッダーを REST URL で提供できます。次にその例を示します。
- http://localhost:8500/rest/RestTest/restService.xml という REST URL の場合、accept パラメーターは application\xml に設定されます。
- (URL の末尾に .json や .xml を付けるのではなく)rest 呼び出しの際に次のヘッダーを使用します。これは、ColdFusion(2021 リリース)以降のバージョンに適用されます。
<cfhttpparam type="header" name="Accept" value="application/json; charset=utf-8">
HTTP コンテンツタイプのネゴシエーション
RESTful Web サービスによって返されるコンテンツタイプは、Accept HTTP ヘッダーに依存します。
クライアント では、Accept リクエストヘッダーを次の順序で設定できます。
- 優先されるコンテンツタイプのカンマ区切りリスト。
- セミコロン(;)で区切った後に、 0 ~ 1 の範囲の浮動小数点数( q=0-1 の形式)で指定します。デフォルト値は 1 です。最小値の 0 はそのコンテンツタイプが受け付けられないことを示し、最大値の 1 は最高の優先度を示します。
2 つのタイプが同じ優先度の場合は、順番の優先度が考慮されます。
例
次の例では、Accept ヘッダーでの優先度を示す値が指定されていないので、クライアントは XML と JSON の両方の形式を使用できます。
GET http://adobe.com/stuff |
次の例のリクエストでは、コンテンツタイプを返す優先度が指定されています。
GET http://adobe.com/stuff |
コンテンツタイプの優先順位は次のようになります。
-
audio/ mpeg (優先度が指定されていないため)
-
text/*(0.9 が最高の値です)
-
application/xml
-
*/
/次の例では、text/* と audio/mpeg に同じ優先度を指定していますが、順番により text/* が優先されます。
GET http://adobe.com/stuff
Accept: text/*;q=0.9, */;q=0.1, audio/mpeg=0.9, application/xml;q=0.5
サブリソースの指定
REST サービスで使用できる関数は、リソース関数、サブリソース関数またはサブリソースロケーターです。
リソース関数
関数レベルでは restPath を指定していないが、{{httpMethod}} を指定している関数です。この場合、CFC の URL にアクセスすると、リソース関数が呼び出されます。
サブリソース関数
restPath と httpMethod の両方を指定している関数です。
サブリソース関数は、CFC によって作成されるリソースのサブリソースを作成するために使用します。サブリソースで cffunction に xhttpMethod 属性がある場合は、次の例で示すように、関数は HTTP リクエストを直接処理できます。
例
Employee.cfc
<cfcomponent rest="true" restPath="/hello"> <cffunction name="sayHello" access="remote" returnType="String" httpMethod="GET" restPath="name"> --------- </cffunction> </cfcomponent>
この例では、httpMethod と restPath が定義されています。 baseurl /hello/name は、URL baseurl /hello に対するサブリソースです。
サブリソースロケーター
httpMethod 属性を指定せず、restPath を指定した場合は、リクエストを処理するコンポーネントを動的に解決できます。返されるオブジェクトはリソースクラスのインスタンスとして扱われ、リクエストを処理するため、またはリクエストを処理するオブジェクトをさらに解決するために、使用されます。
例
この例では、StudentService.cfc と Student.cfc が REST リソースです。StudentService.cfc では、getStudent 関数がコンポーネントを返します。関数では、Student のオブジェクトが作成され、値 name および age が設定されます。オブジェクトが戻り値の型に指定されている場合、リクエストされた httpmethod を含むオブジェクトに定義された関数が呼び出されます。restPath が指定されているので、StudentService.cfc を直接呼び出すことができます。StudentService.cfc の関数 getStudent はサブリソースロケーターとして機能し、Student.cfc を返すので、Student.cfc は StudentService.cfc を介してのみ呼び出すことができます。StudentService.cfc:
<cfcomponent rest="true" restpath="/studentService"> <cffunction name="addStudent" access="remote" returntype="void" httpmethod="POST"> <cfargument name="name" type="string" required="yes" restargsource="Form"/> <cfargument name="age" type="numeric" required="yes" restargsource="Form"/> <!---学生をデータベースに追加します。---> </cffunction> <cffunction name="getStudent" access="remote" returntype="student" restpath="{name}-{age}"> <cfargument name="name" type="string" required="yes" restargsource="Path"/> <cfargument name="age" type="string" required="yes" restargsource="Path"/> <!---学生オブジェクトを作成し、オブジェクトを返します。このオブジェクトは、ここでリクエストを処理します。---> <cfset var myobj = createObject("component", "student")> <cfset myobj.name = name> <cfset myobj.age = age> <cfreturn myobj> </cffunction> </cfcomponent>
Student.cfc
<cfcomponent> <cfproperty name="name" type="string"/> <cfproperty name="age" type="numeric"/> <!---学生の詳細情報を取得します。---> <cffunction name="getStudent" access="remote" returntype="String" httpmethod="GET" produces="text/xml"> <!---データベースから学生を取得します。---> <!---データベースから名前と年齢が一致する学生を取得します。---> <cfset st.name = "Thomas"> <cfset st.age = "25"> <cfset st.surname = "Paul"> <cfset str = "<student><name>" & st.name & "</name><age>" & st.age & "</age><surname>" & st.surname & "</surname></student>"> <cfreturn str> </cffunction> <! ---学生の詳細情報を更新します。---> <cffunction name="updateStudent" access="remote" returntype="void" httpmethod="PUT"> <!---データベースから学生を取得します。---> <! ---データベース内の学生を更新します。---> <cfset st.name = name> <cfset st.age = age> </cffunction> <!---学生を削除します。---> <cffunction name="deleteStudent" access="remote" returntype="String" httpmethod="DELETE"> <!---データベースから学生を削除します。---> <!---<cfset st = deleteStudentFromDB(name)>---> <cfreturn "Student deleted"> </cffunction> </cfcomponent>
Student.cfm
<! ---学生の追加---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService" method="post" result="res"> <cfhttpparam type="formfield" name="name" value="Thomas" > <cfhttpparam type="formfield" name="age" value="25" > </cfhttp> <cfoutput>学生が追加されました</cfoutput> </br> </br> <! ---詳細の取得---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="get" result="res"> </cfhttp> <cfoutput>#xmlformat(res.filecontent)#</cfoutput> </br> </br> <! ---学生の詳細情報の更新---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="put" result="res"> </cfhttp> <cfoutput>学生を更新しました</cfoutput> </br> </br> <! ---学生の削除---> <cfhttp url="http://localhost:8500/rest/RestTest/studentService/Thomas-25" method="delete" result="res"> </cfhttp> <cfoutput>学生が削除されました</cfoutput>
HTTP レスポンス
デフォルトでは、ColdFusion は HTTP の成功および失敗のレスポンスを次のようにクライアントに提供します。
成功レスポンス
デフォルトのレスポンス |
説明 |
---|---|
200 OK |
レスポンスに body がある場合に送信されます。 |
204 No Content |
レスポンスに body がない場合に送信されます。 |
エラーレスポンス
デフォルトのレスポンス |
説明 |
---|---|
404 Not found |
リクエストの URL が無効です。 |
406 Not Acceptable |
REST サービスのどの関数も、クライアントによってリクエストされた MIME タイプを生成できません。 |
415 Unsupported Media Type Error |
リソースはクライアントリクエストの MIME タイプを使用できません。 |
405 Method not allowed |
クライアントが、リクエスト HTTP メソッドがバインドされない、有効な URI の HTTP メソッドを呼び出す場合。このエラーは、クライアントが HTTP HEAD メソッドおよび OPTIONS メソッドを呼び出す場合は、表示されません。特定の URI に HEAD リクエストを提供できるリソースメソッドは利用できませんが、GET を処理できるメソッドが存在する場合は、それが呼び出されて、リクエスト本文なしでそのメソッドからのレスポンスを返します。OPTIONS を処理できる既存のメソッドがない場合、自動的に生成された意味のあるレスポンスが、Allow ヘッダーを設定されて送信されます。 |
カスタムレスポンス
ColdFusion で使用できるデフォルトのレスポンスに加えて、カスタムレスポンスを設定できます。
例えば、成功レスポンスの 201 Created を提供する必要があるとします。このようなデフォルトのレスポンスはありません。送信できるのは 200 OK または 204 No Content だけです。
この場合は、次のいずれかの方法でカスタムレスポンスを作成できます。
restSetResponse を使用したカスタム成功レスポンスの送信
CFC を REST サービスとして定義する場合は、cffunction(カスタムレスポンスを送信する関数)で returnType を void に設定します。次に例を示します。
<cffunction name="create" httpMethod="POST" produces="application/xml" returnType="void"> <cffunction>
次の例に示すように、cffunction で送信するカスタムレスポンスの構造体を作成します。
<cfset response=structNew()> <cfset response.status=201> <cfset response.content="<customer id="&id&"><name>"&name&"</name></customer>"> <cfset response.headers=structNew()> <cfset response.headers.location="http://localhost:8500/rest/CustomerService/customers/123">
この例では、レスポンスのステータスとして 201、および送信するコンテンツを設定しています。例えば、顧客の詳細および POST リクエストのレスポンスを作成した場所です。
カスタムレスポンスでステータスを指定しないと、レスポンスのステータスとして 500 Internal server error が送信されます。
次のように、restSetResponse 関数を使用します。
restSetResponse(response );
cfthrow を使用したカスタムエラーレスポンスの送信
カスタムエラーレスポンスを送信するものとします。例えば、次のような場合を考えてみます。method.service.cfc
<cffunction name="getCustomer" httpMethod="GET" produces="application/xml" restPath="{id}" return="string"> <cfargument name="id" type="numeric" argtype="PathParam"> <!---顧客を取得します。---><cffunction>
この場合、顧客データベースがあり、GET HTTP リクエストを /customers/123 で行っています。しかし、指定した ID 123 の顧客が利用できないことがわかります。そのため、デフォルトでは利用できないクライアントに 404 Resource Not Found レスポンスを送信します。この場合、cfthrow を使用して次のようにカスタムエラーレスポンスを送信します。
<cfthrow type="RestError" errorcode="404">
Application.cfc の変更
REST サポート用に Application.cfc が次のように拡張されました。
変数 |
説明 |
---|---|
this.restsettings.cfclocation |
特定の場所においてのみ CFC を公開するには、REST CFC が配置されるディレクトリのカンマ区切りリストを提供します。ディレクトリパスは、絶対パスまたは相対パスを設定できます。設定しないと、アプリケーションルートからのすべての CFC が公開されます。 |
this.restsettings.skipCFCWithError |
エラーが発生した場合、公開を継続し、例外の原因となる CFC を無視します。true の場合、エラーの CFC は無視され、CFC の残りは公開されます。デフォルトでは、false に設定されています。False に設定されている場合、 大文字と小文字 エラーが発生すると、アプリケーション自体は公開されません。ただし、その他の登録済み アプリケーション は公開されます。アプリケーションの起動中にエラーが発生した場合は、エラーが コンソール に出力されます。各アプリケーションには、問題を記録するため、個別にログファイルがあります。 |
REST Web サービスの拡張
RESTful CFC を拡張するときは、次の条件が適用されます。
基本 CFC の関数に対して、REST 属性を定義できます。そのため、基本 CFC から拡張するすべての CFC は、REST 属性を継承します。次の例では、CustomerResource. cfc は BaseCustomerResource.cfc:BaseCustomerResource.cfc を拡張します。
<cfcomponent> <cffunction name="SayPlainHello" access="remote" produces="text/plain" returntype="string" httpmethod="POST"> <cfreturn "BaseCustomerResource Plain"> </cffunction> <cffunction name="SayXMLHello" access="remote" produces="text/xml,application/xml" returntype="string" httpmethod="POST"> <cfreturn "BaseCustomerResource XML"> </cffunction> </cfcomponent>
BaseCustomerResource.cfc には、CFC 内の関数に適用されるすべての REST 属性があります。BaseCustomerResource.cfc を定義した後、BaseCustomerResource.cfc を拡張する CustomerService.cfc を次のように定義できます。Customerservice.cfc
<cfcomponent rest="true" restpath="/customerservice" extends="BaseCustomerResource"> <cffunction name="SayPlainHello" access="remote" returntype="string"> <!--- メソッドを実装します。---> <cfreturn "CustomerResource Plain"> </cffunction> <cffunction name="SayXMLHello" access="remote" returntype="string"> <!--- メソッドを実装します。---> <cfreturn "CustomerResource XML"> </cffunction> </cfcomponent>
BaseCustomerResource.cfm
<cfhttp url="http://localhost:8500/rest/RestTest/customerservice" method="post" result="res"> <cfhttpparam type="header" name="accept" value="text/plain" > </cfhttp> <cfoutput>#res.filecontent#</cfoutput> </br> </br> <cfhttp url="http://localhost:8500/rest/RestTest/customerservice" method="post" result="res"> <cfhttpparam type="header" name="accept" value="application/xml" > </cfhttp> <cfoutput>#res.filecontent#</cfoutput> </br> </br>
rest および restPath 以外の REST 属性は、CustomerService.cfc 内では必要ありません。
RESTful CFC を継承する際に、拡張する CFC で使用されている属性の上書きを選択できます。例えば、次の CFC は BaseCustomerResource.CFC を拡張しますが、SayPlainHello 関数は基本 CFC の関数を上書きしています。
<cfcomponent rest="true" restPath="/customerservice" extends="BaseCustomerResource"> <cffunction name="SayPlainHello" access="remote" produces="text/plain" returntype="string" httpmethod="PUT"> <cfargument name="username" type="string" argtype="pathparam"> <!--- メソッドを実装します。---> </cffunction> <cffunction name="SayXMLHello" access="remote" returntype="string"> <cfargument name="username" type="string"> <!--- メソッドを実装します。---> </cffuntion> </cfcomponent>
関数内の 1 つの属性だけを上書きする場合でも、すべての REST 属性を再指定する必要があります。
- REST サービスとして使用するには、継承された CFC で REST 属性(rest/restPath)を指定する必要があります。基本 CFC で定義するだけでは機能しません。
REST サービスとデータ交換形式
ColdFusion の REST サービスは、Web 経由で送信できるように、XML または JSON 形式で表すことができます。サービスで使用されている ColdFusion のデータ型の XML または JSON へのシリアル化/シリアル化解除は、ColdFusion が暗黙で行います。
REST 対応の関数は、ColdFusion のデータ型であるクエリー、構造体、CFC の 配列 、XML、文字列、数値、 ブール値 、日付、バイナリ(XML 用)を引数として受け取ることができます。
ColdFusion は、データを XML および JSON の定義済み形式にシリアル化します。同様に、ColdFusion は、本文が ColdFusion によって定義されている形式である場合にのみ、本文をシリアル化解除します。
REST サービスの XML シリアル化
シリアル化の仕様
- リクエストの Accept ヘッダーは、text/ xml または application/ xml である必要があります。
- 必要な MIME タイプを生成できる関数がサービス内に必要です。
- 関数は、ColdFusion がサポートするいずれかのデータ型を返す必要があります。
循環配列はサポートされません。公開されたシリアル化済み文字列を表示できますが、次の例で説明するように意図した出力になりません。
<cfset this.arr1 = arrayNew(1)> <cfset this.arr1[1] = "1"> <cfset this.arr1[2] = this.arr1> <cfset this.arr1[3] = "3">
変数に配列を代入するとき(この場合は <cfset this.arr12 = this.arr1>)、arr1 を arr1 の 2 番目のインデックスの項目として代入します。ColdFusion は暗黙で新しい配列を作成し、arr1 から新しく作成した配列にデータをコピーします。新しく作成された配列は、arr1 の 2 番目のインデックスに代入されます。このため、両方のインスタンスは異なり、その結果、循環依存関係が影響を受けます。シリアル化の際に、次の出力が得られます。
<array id="1" size="3"> <item index="1" type="string">1</item> <item index="2" type="array"> <array id="2" size="1"> <item index="1" type="string">1</item> </array> </item> <item index="3" type="string">3</item> </array>
見るとわかるように、内側の配列は最初の要素の後で切り捨てられています。
シリアル化解除の仕様
- リクエストのコンテンツは、ColdFusion で指定されている定義済みの形式である必要があります(詳しくは、「形式の定義」のセクションを参照)。
- リクエストのコンテンツタイプは、text/ xml または application/ .xml に にする必要があります。
- リクエストの MIME タイプを使用できる関数がサービス内に必要です。
- cfargument では restArgSource 属性および restArgName 属性を指定できません。つまり、リクエストの本文のデータのみを送信できます。
- cfargument 型は ColdFusion がサポートするデータ型である必要があります。
- restArgSource 属性を指定しない引数は 1 つしか存在できません。リクエストの本文全体が、引数の型にシリアル化解除されます。
- 循環配列はサポートされません。
形式の定義
クエリ
- XML のルート要素は query である必要があります。
- 循環依存関係を処理するには、ID 属性を使用します。
- 有効な属性値は、文字列、日付、ブール、数値、ドキュメント、クエリ、構造体、配列、CFC(値が CFC インスタンスの場合)です。
例
次の例では、ルート query 要素には、columnnames と rows の 2 つの子要素があります。columnnames はクエリーの列の名前です。rows は複数の row 要素のデータを持つことができます。ここで、行の列の順序は、columnames で定義されている列と一致する必要があります。行内の列ごとに type 属性が必須です。type 属性の値には、ColdFusion の任意のデータ型を設定できます。
<query id="1"> <columnnames> <column name="columnnameone"/> <column name="columnnametwo"/> </columnnames> <rows> <row> <column type="string">value one</column> <column type="string">value two</column> </row> <row> <column type="number">444.0</column> <column type="string">value four</column> </row> </rows> </query>
構造体
- XML のルート要素は である必要があります。 構造体 。
- 循環依存関係を処理するには、ID 属性を使用します。
- struct は複数の entry 子要素を持つことができます。つまり 、 つまり、シリアル化される Struct インスタンス内のキーと値のペアです。entry 要素には 2 つの必須属性 name(エントリの名前)と type(エントリの値の型)が必要です。type 属性の値には、ColdFusion のいずれかのデータ型を設定できます。
例
<struct id="1"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct>
CFC コンポーネント
- XML のルート要素は である必要があります。 component です。
- ID 属性は循環依存関係を処理する際に使用します。
- name 属性は、CFC の webroot からの完全修飾名を提供する必要があります。
- component 要素は、複数の property 子要素を含むことができます。
- property 要素は、 cfproperty の値( cfcomponent で定義されているもの)です。
- property の name 属性は、定義されている cfproperty の名前に対応します。
- type 属性は cfproperty の型を指定します。
- コンポーネント内の いずれかのプロパティが null 値を持つ場合、そのプロパティはシリアル化された形式には含まれません。これはシリアル化解除にも適用されます。
例
Student.cfc
<component id="1" name="testrest.student"> <property name="name" type="string">paul</property> <property name="age" type="number">444.0</property> <property name="dob" type="date">478377000000</property> </component>
次に示す例では、 testrest .student は、CFC Student.cfc が webroot 配下の testrest ディレクトリにあるという意味です。
配列および cfcomponent の配列の形式
- ルート要素は array である必要があります。
- size 属性は配列の長さを指定します。
- type 属性は、array 要素の場合は必須ではありません が、 item 要素の場合は必須です。
- 配列が cfcomponent 配列の場合、array 要素の type 属性は CFC の完全修飾名である必要があります。
- array 要素には複数の item 子要素が含まれます。配列内の非 null 要素だけがシリアル化されます。
- Item 要素には、次の2つの属性があります。 index これにより、その配列および型でアイテムのインデックスが指定されます。
例
次の例では、2 つの struct オブジェクトを含む配列を示します。
<array id="1" size="2"> <item index="0" type="struct"> <struct id="2"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct> </item> <item index="1" type="struct"> <struct id="3"> <entry name="name" type="string">paul</entry> <entry name="age" type="string">25</entry> <entry name="address" type="string">some other address</entry> <entry name="eyecolor" type="string">black</entry> <entry name="income" type="string">40000</entry> </struct> </item> </array>
例:CFC の配列のシリアル化
次の例では、CFC の配列の XML および JSON 形式へのシリアル化を示します。
-
arrayCFCdefinition.cfc の配列を作成します。
<cfcomponent> <cfproperty name="str" type="string"/> </cfcomponent>
-
arrayCFC.cfc が、必要な配列を次のように生成します。
<cfcomponent restpath="arrayOfCFC"> <cffunction name="func1" access="remote" output="false" returntype="arrayCFCdefinition[]" httpmethod="get" produces="text/xml"> <cfset arrCFC = arraynew(1)> <cfloop from=1 to=2 index="i"> <cfset obj = createObject("component", "arrayCFCdefinition")> <cfset obj.str = i> <cfset arrayAppend(arrCFC, obj)> </cfloop> <cfreturn arrCFC> </cffunction> <cffunction name="func2" access="remote" output="false" returntype="arrayCFCdefinition[]" httpmethod="get" produces="text/json"> <cfset arrCFC = arraynew(1)> <cfloop from=1 to=2 index="i"> <cfset obj = createObject("component", "arrayCFCdefinition")> <cfset obj.str = i> <cfset arrayAppend(arrCFC, obj)> </cfloop> <cfreturn arrCFC> </cffunction> </cfcomponent>
-
次のようにして、リソースにアクセスします。
XML の場合
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="get" result="res1"> <cfhttpparam type="header" name="accept" value="text/xml"> </cfhttp>
JSON の場合
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="get" result="res2"> <cfhttpparam type="header" name="accept" value="text/json"> </cfhttp>
-
レスポンスとして次のようなシリアル化された出力を受け取ります。
XML の場合
<array id="1" size="2" type="cfsuite.restservices.restservices.new.ArrayCFCdefinition"> <item index="1" type="COMPONENT"> <component id="2" name="cfsuite.restservices.RESTServices.New.arrayCFCdefinition"> <property name="STR" type="NUMBER"> 1.0 </property> </component> </item> <item index="2" type="COMPONENT"> <component id="3" name="cfsuite.restservices.RESTServices.New.arrayCFCdefinition"> <property name="STR" type="NUMBER"> 2.0 </property> </component> </item> </array>
JSON の場合
[{"Str":1},{"Str":2}]
例:CFC の配列:シリアル化解除
次の例では、CFC の配列の XML 形式からのシリアル化解除を示します。
CFC の配列のシリアル化解除 JSON ではサポートされていません。
-
arrayCFCdefinition.cfc の配列を作成します。
<cfcomponent> <cfproperty name="str" type="string"/> <cffunction name="check" returntype="any"> <cfreturn this.str> </cffunction> </cfcomponent>
-
arrayCFC.cfc が、必要な配列を次のように生成します。
<cfcomponent> <cffunction name="func3" access="remote" output="false" returntype="string" httpmethod="put" produces="text/xml" consumes="text/xml"> <cfargument name="arg" type="arrayCFCdefinition[]"/> <cfif arg[2].check() eq "2"> <cfreturn "true"> <cfelse> <cfreturn "false"> </cfif> </cffunction> </cfcomponent>
-
次のようにして、XML のリソースにアクセスします。
<cfhttp url="http://127.0.0.1:8500/rest/RestTest/arrayOfCFC" method="put" result="res3"> <cfhttpparam type="header" name="content-type" value="text/xml"> <cfhttpparam type="header" name="accept" value="text/xml"> <cfhttpparam type="body" value="<ARRAY ID=""1"" SIZE=""2"" TYPE=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><ITEM INDEX=""1"" TYPE=""COMPONENT""><COMPONENT ID=""2"" NAME=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><PROPERTY NAME=""STR"" TYPE=""NUMBER"">1.0</PROPERTY></COMPONENT></ITEM><ITEM INDEX=""2"" TYPE=""COMPONENT""><COMPONENT ID=""3"" NAME=""cfsuite.restservices.restservices.new.ArrayCFCdefinition""><PROPERTY NAME=""STR"" TYPE=""NUMBER"">2.0</PROPERTY></COMPONENT></ITEM></ARRAY>"> </cfhttp>
-
関数を参照します。配列の 2 番目のインデックスの arrayCFC definition.cfc のプロパティの値を確認します。
文字列、ブール、数値、バイナリ、日付
リクエストの本文で値を直接指定します。
循環依存関係の処理
ColdFusion では、循環依存関係は ID 参照を使用して処理します。すべての ColdFusion 複合データ型には、シリアル化時に一意の ID があります。同じオブジェクトを別の場所でシリアル化する必要がある場合は、再度オブジェクトをシリアル化する代わりに、ID を使用して既にシリアル化されているデータが参照されます。次の例では、メインのオブジェクトは構造体です。構造体にはオブジェクトの配列が含まれます。配列には 2 つの要素があり、どちらの要素も構造体の同じインスタンスです。シリアル化の際に、配列の最初の要素はそのままシリアル化されます。シリアル化された構造体の ID は 2 です。このオブジェクトは既にシリアル化されているので、2 番目の要素をシリアル化する代わりに、IDREF 属性を使用して既にシリアル化されている構造体インスタンスを参照します。
<struct id="1"> <entry name="arrayinastruct" type="array"> <array id="2" size="2"> <item index="0" type="struct"> <struct id="3"> <entry name="name" type="string">joe</entry> <entry name="age" type="string">30</entry> <entry name="address" type="string">101 some drive, pleasant town, 90010</entry> <entry name="eyecolor" type="string">blue</entry> <entry name="income" type="string">50000</entry> </struct> </item> <item index="1" type="struct"> <struct idref="3"/> </item> </array> </entry> </struct>
シリアル化解除のときにも ColdFusion によってオブジェクト参照が処理されます。
JSON のシリアル化と REST サービス
シリアル化の仕様
- リクエストの Accept ヘッダーのコンテンツタイプは、text/JSON、application/JSON または text/plain である必要があります。
- REST サービスには、必要な MIME タイプを処理できる関数が必要です。
- 関数 は、ColdFusion がサポートするバイナリ以外のいずれかのデータ型を返す必要があります。
循環の動作はサポートされていません。ただし、配列の場合は、公開されたシリアル化済み文字列を表示できますが、次の例で説明するように意図した出力になりません。
<cfset this.arr1 = arrayNew(1)> <cfset this.arr1[1] = "1"> <cfset this.arr1[2] = this.arr1> <cfset this.arr1[3] = "3">
変数に配列を代入するとき(この場合は <cfset this.arr12 = this.arr1>)、arr1 を arr1 の 2 番目のインデックスの項目として代入します。ColdFusion は暗黙で新しい配列を作成し、arr1 から新しく作成した配列にデータをコピーします。新しく作成された配列は、arr1 の 2 番目のインデックスに代入されます。このため、両方のインスタンスは異なり、その結果、循環依存関係が影響を受けます。シリアル化の際に、次の出力が得られます。
[1,[1],3]
見るとわかるように、内側の配列は最初の要素の後で切り捨てられています。
シリアル化解除の仕様
- リクエストのコンテンツは、ColdFusion によって指定されている定義済みの形式です。
- リクエストのコンテンツタイプは、text/JSON、application/JSON または text/plain です。
- サービスの関数は、リクエストの MIME タイプを使用します。
- cfargument では、restargsource 属性および restargname 属性は指定されていません。
- cfargument の型は、バイナリまたは CFC 定義以外の ColdFusion がサポートするデータ型です。
- restArgSource 属性が指定されない引数は 1 つだけです。リクエストの本文全体が、引数の型にシリアル化解除されます。
- 循環の動作はサポートされていません。ただし、循環配列の場合は、公開されたシリアル化解除済み文字列を表示できますが、意図した出力になりません。
形式の定義
クエリの形式
{'COLUMNS':['columnNameOne','columnNameTwo'],'Data':[['value one','value two'],['444.0','value four']]}
構造体の形式
{'NAME':'joe','AGE':30,'ADDRESS':'101 Some Drive, Pleasant Town, 90010','EYECOLOR':'blue','INCOME':50000}
コンポーネントの形式
{'NAME':'Paul','AGE':444.0,'DOB':'July, 27 2011 00:00:00'}
コンポーネントのシリアル化解除はサポートされません。
配列の形式
[{'NAME':'joe','AGE':30,'ADDRESS':'101 Some Drive, Pleasant Town, 90010','EYECOLOR':'blue','INCOME':50000},{'NAME':'paul','AGE':25,'ADDRESS':'Some other address','EYECOLOR':'black','INCOME':40000}]
文字列、ブール、数値、日付
リクエストの本文で値を直接指定します。----
GZip エンコードのサポート
リクエストに、「gzip」の Content-Encoding ヘッダーが含まれる場合、(もしあれば)リクエストエンティティは、gzip アルゴリズムを使用して圧縮されません。リクエストに「gzip」および「If-None-Match」ヘッダーを含む Accept-Encoding ヘッダーが含まれている場合、entitytag の値が確認され、-gzip 接尾辞が含まれる場合は、この接尾辞が削除され、それ以外は、「If-None-Match」ヘッダーが完全に削除されます。
リクエストに、「gzip」の Accept-Encoding ヘッダーが含まれる場合、(もしあれば)リクエストエンティティは、gzip を使用して圧縮され、「gzip」の Content-Encoding ヘッダーがレスポンスに追加されます。このフィルターはアクティブなので、リソース表現は圧縮できます。値「Accept-Encoding」が Vary ヘッダーに追加されます。任意の entityTag が使用され、コンテンツが gzip で圧縮されている可能性がある場合、「-gzip」接尾辞が entitytag 値に追加されます。
サイトレベルの REST アプリケーションのサポート
ColdFusion 10 では、たとえアプリケーションが異なるホストに存在する場合でも、複数のアプリケーションで同じ名前を持つことはできません。ColdFusion 11 では、REST 機能が強化され、異なるホストの複数のアプリケーションに同じ名前を指定できます。また、仮想ホストごとにデフォルトのアプリケーション(REST サービスを含む)を 1 つ設定できます。
次のオプションのいずれかを使用して、REST サービスを含むディレクトリを登録できます:
- アプリケーション設定の自動登録
- ColdFusion Administrator コンソール
- ColdFusion Admin API
- restInitApplication メソッド
オプション 1:アプリケーション設定の自動登録
ColdFusion 11 では、新しいアプリケーション設定の「自動登録」が導入されました。
- アプリケーションの自動登録を有効にする場合、autoregister を true に設定します:
<cfset this.restsettings.autoregister="true"/>
- servicemapping の指定はオプションです。 servicemapping が指定されていない場合、"this.name"/アプリケーション名をデフォルトとして使用します。
<cfset this.restsettings.servicemapping="testmapping"/>
- Specify the usehost または hostname を指定し、 usehost 属性を true に設定すると、URL からホスト名が解析されます。usehost="True" は、REST サービス登録のデフォルト値です。usehost=true の場合、ホスト名は、URL から取得されます。ホスト名は、登録に使用されます。ホストが指定されていない場合、つまり、usehost="False" の場合、ホスト名を持たないすべてのアプリケーションおよび任意のホストからのすべてのリクエストは、サービスが提供されます。
<cfset this.restsettings.usehost=true/>
- ホスト名に明示的に名前を指定して、ホスト名を作成します。ホスト名が記載されていない場合、 usehost の名前が デフォルトになります 。
<cfset this.restsettings.host="www.adobe.com"/>
- isDefault を true に設定すると、アプリケーションがデフォルトアプリになります。
<cfset this.restsettings.isDefault=true/>
アプリケーションに最初のリクエストが到達し、そのリクエストが リクエストでない場合、 REST リクエストでない場合、 アプリケーションが起動して登録されます。どちらの場合も usehost と host を指定しないと、アプリは host 名なしで登録されます。
最初のリクエスト自体が REST リクエストである場合、アプリケーションは開始されません。
オプション 2:ColdFusion Administrator コンソールを使用した REST アプリケーションの登録
- Administrator コンソールを使用して、REST 対応 CF コンポーネントを含むディレクトリを登録します。Adobe ColdFusion 11 Administrator コンソール/データとサービス/REST サービスを選択します。
- ColdFusion が REST 対応 CF コンポーネントのセットを含むディレクトリを検索する際のルートパス(またはアプリケーションのパス)を参照して選択します。
(オプション)「サービスマッピング」セクションで、アプリケーション名の代わりに仮想マッピングを指定します。フォルダーに Application.cfc ファイルがあり、アプリケーション名が指定されている場合、アプリケーション名を使用してディレクトリ内の REST サービスを特定します。
(オプション)ホスト名を入力します。これにより、選択したアプリケーションをホストとマッピングできます。ホストごとにデフォルトアプリケーションを持つことができ、同じアプリケーション名を持つ複数のアプリケーションが異なるホストにマッピングできます。 - 「デフォルトアプリケーションとして設定する」オプションを設定することで、REST アプリケーションをデフォルトアプリケーションとして設定します。このオプションを選択することで、URI でサービスマッピングやアプリケーション名を指定する必要がなくなります。
- 「サービスを追加」ボタンをクリックして、ディレクトリの登録を完了します。
- 「アクティブな ColdFusion REST サービス」表示テーブルを表示して、アクティブなサービスのマッピングのリストを表示します。将来のサービスマッピングの編集または削除に、同じ表示テーブルを使用できます。
オプション 3:ColdFusion Admin API を使用した REST アプリケーションの登録
CFIDE. adminapi .extensions CFC で定義されている関数を使用して REST アプリケーションを管理します。その関数を次に示します。
- registerRESTService(path[,serviceMapping[,host[,isdef]]]:この関数は、REST アプリケーションを登録します。ルートパスは、REST 対応 CF コンポーネントを含むディレクトリを指定します。必要に応じて、REST アプリケーション、 ホスト名 、および isdefault のサービスマッピングを指定することもできます。
- getRESTServices():この関数は、ColdFusion Administrator で登録した REST サービスの配列を返します。
- deleteRESTService(rootPath):この関数は、ColdFusion Administrator で登録された REST アプリケーションのうち指定されたものを削除します。
- refreshRESTService(rootPath):REST 対応 CF コンポーネントに変更を加えた場合、この関数を呼び出すことで、登録されたアプリケーションを更新できます。
- getDefaultRestService(): サーバー全体 でデフォルトの REST アプリケーションを返します。
- getAllDefaultRESTServices:すべてのデフォルト REST サービスを返します。値は、パスとホストのペアの配列です。
オプション 4:restInitApplication メソッドを使用した REST アプリケーションの登録
また、メソッド restInitApplication を呼び出すことでも、REST アプリケーションを登録できます。
構文を次に示します:
restInitApplication(rootPath[,serviceMapping[,options]])
options はオプションの引数です。options 構造体で、次を渡すことができます:
- ホスト
- useHost
- isDefault
host を明示的に指定することで登録する場合:
<cfset str=structNew()> <cfset str.host = "www.site1.com:82"> <cfset str.isDefault = "true"> <cfset RestInitApplication("C:\dev\ColdFusion\cf_main\cfusion\wwwroot\withhostAndDefault", "withhostAndDefault", str)> App registered
useHost 属性を指定することで登録する場合:ホスト名は、リクエスト URL から抽出され、登録に使用されます。
<cfset str=structNew()> <cfset str.useHost = "true"> <cfset str.isDefault = "true"> <cfset RestInitApplication("C:\dev\ColdFusion\cf_main\cfusion\wwwroot\withhostAndDefault", "withhostAndDefault", str)> App registered
このタスクを実行するのに、管理者権限は必要ありません。構文を次に示します: restInitApplication(rootPath[,serviceMapping[,options]]) |
- options には、 host、useHost、isDefault を指定できます。このオプションの使用方法は、autoRegister 機能と同じです。
- 既に Administrator モジュールを使用してアプリケーションを登録済みの場合、restInitApplication を呼び出してREST サービスを更新します。
- restDeleteApplication 関数を使用して REST サービスを削除します。構文は restDeleteApplication(rootPath) です。
プラグ可能なシリアライザーおよびデシリアライザーのサポート
application.cfc で、複合型のシリアライズおよびデシリアライズのための独自のハンドラーを登録できます。シリアライザーが指定されていない場合、ColdFusion は、デフォルトのシリアル化メカニズムを使用します。
例:次のパラメーターでシリアル化する必要のある電話帳がある場合:
- 主要なデータ構造は配列です。
- 配列の各要素は、構造体です。
- 構造体には、2 つの要素が含まれます。
- 1 番目は連絡先の名前で、2 番目はコードおよび電話番号を含む構造体です。
配列
Struct [ name(String], phoneNo(Struct) [ code(String), no(String) ] ] Struct [ name(String], phoneNo(Struct) [ code(String), no(String) ] ]
またこの例では、構造体のみを単純な形式でシリアル化し、次のような結果を得ることを目的とします。
<Array size="1"> <Item index="1"> <root> <Name>Paul</Name> <PhoneNo> <root> <Code>080</Code> <No>411150326</No> </root> </PhoneNo> </root> </Item> </Array>
ColdFusion 11 の強化された REST 機能により、ユーザーは、デフォルトのシリアル化メカニズムを使用する代わりに、プラグインのカスタムシリアライザーを使用できます。カスタムシリアライザーには、4 つの関数があります。
- CanSerialize:ブール値を返し、リクエストの「承認タイプ」を引数として取ります。 customserialzer によってデータを渡された引数の型にシリアル化する場合は true を返すことができます。
- Serialize:主要なシリアル化ロジックは、この関数で実装される必要があります。canSerialize がリクエストに「True」を返す場合、ColdFusion はこの関数を使用してシリアル化します。canSerialize がリクエストに「false」を返す場合、ColdFusion はデフォルトのシリアル化メカニズムを使用してシリアル化します。
- CanDeserialize:ブール値を返し、リクエストの「 コンテンツタイプ 」を引数として使用します。 customserialzer でデータをシリアル化解除する場合は、true を返すことができます。
- DeSerialize:主要なシリアル化解除ロジックは、この関数で実装される必要があります。canDeSerialize がリクエストに「True」を返す場合、ColdFusion はこの関数を使用してシリアル化解除します。canDeSerialize がリクエストに「false」を返す場合、ColdFusion はデフォルトのシリアル化解除関数を使用してシリアル化解除します。
次の CustomSerializer コード例は、上記で説明したシナリオ(電話帳の シリアル化 /シリアル化解除のカスタマイズ)で結果を出すのに役立ちます:
<cfcomponent> <cffunction name="serialize" access="remote" returntype="String"> <cfargument name="arg" type="any" hint="The object to be serialized"/> <cfargument name="type" type="string" hint="The accept header of the request in array format.配列内のタイプの順序はヘッダーの MIME タイプの優先度に従います。"/> <cfset var result = ""> <cfset var key = ""> <cfif arguments.type eq "XML"> <cfif isStruct(arguments.arg)> <cfset result = "<root>"> <cfloop collection="#arguments.arg#" item="key"> <cfset result = result & "<" & key & ">"> <cfset result = result & serializeXML(arguments.arg[key], true)> <cfset result = result & "</" & key & ">"> </cfloop> <cfset result = result & "</root>"> <cfreturn result> <cfelse> <! --- SerializeXML は ColdFusion 11 で追加された新しい関数です。この関数は、This function will serialize the object to XML using ColdFusion のデフォルトのシリアル化メカニズムを使用してオブジェクトを XML にシリアル化します。"---> <cfreturn serializeXML(arguments.arg)> </cfif> <cfelseif arguments.type eq "JSON"> <cfdump var="#arguments.arg.getClass().getName()#" output="console"> <cfif arguments.arg.getClass().getName() eq "java.lang.String"> <cfreturn "test" & arguments.arg> <cfelse> <cfreturn serializeJSON(arguments.arg)> </cfif> <cfelse> <! --- Serialize is a new function added in ColdFusion 11.This function will serialize the object to a a specified type using ColdFusion's default serialization mechanism.---> <cfreturn serialize(arguments.arg, arguments.type)> </cfif> </cffunction> <cffunction name="canSerialize" access="remote" returntype="boolean"> <cfargument name="type" type="string"/> <cfif arguments.type eq "XML"> <cfreturn true> <cfelseif arguments.type eq "JSON"> <cfreturn true> <cfelse> <cfreturn false> </cfif> </cffunction> <cffunction name="canDeserialize" access="remote" returntype="boolean"> <cfargument name="type" type="string"/> <cfif arguments.type eq "XML"> <cfreturn true> <cfelseif arguments.type eq "JSON"> <cfreturn true> <cfelse> <cfreturn false> </cfif> </cffunction> <cffunction name="deserialize" access="remote" returntype="any"> <cfargument name="arg" type="String" hint="The string to be deserialized"/> <cfargument name="type" type="String" hint="The content-type header of the request."/> <cfset var xmlDoc = ""> <cfset var result = ""> <cfset var numEntries = ""> <cfset var key = ""> <cfset var value = ""> <cfif arguments.type equals "XML" and isXml(arguments.arg)> <cfset xmlDoc = xmlParse(arguments.arg)> <cfif xmlDoc.XmlRoot.XmlName equals "root"> <cfset result = StructNew()> <cfset numEntries = ArrayLen(xmlDoc.root.XMLChildren)> <cfloop index="i" from="1" to="#numEntries#"> <cfset key = xmlDoc.root.XMLChildren[i].XmlName> <cfif ! len(Trim(xmlDoc.root.XMLChildren[i].XMLText))> <cfset value = deserializeXML(ToString(xmlDoc.root.XMLChildren[i].XMLChildren[1]), true)> <cfelse> <cfset value = deserializeXML(xmlDoc.root.XMLChildren[i].XMLText, true)> </cfif> <cfset result[key] = value> </cfloop> <cfreturn result> <cfelse> <cfreturn deserializeXML(arguments.arg, true)> </cfif> <cfelse> <cfreturn deserializeXML(arguments.arg, true)> </cfif> </cffunction> </cfcomponent>
実装した CustomSerializer は、application.cfc で指定できます。
<cfset this.customSerializer="CustomSerializer">