tag:blogger.com,1999:blog-79644849364708291182024-03-27T15:35:16.268+09:00Modegramming Styleasamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.comBlogger413125tag:blogger.com,1999:blog-7964484936470829118.post-68791714487105305982024-02-29T18:00:00.003+09:002024-02-29T18:00:00.136+09:00Cozyモデル駆動開発/ビジネス・モデリング<div><p>モデル駆動開発ワークベンチCozyを使用したモデル駆動開発を具体的に考えて、Cozyへの機能要件を洗い出しています。</p><p>Cozyを使用したモデル駆動開発をCozyモデル駆動開発 (Cozy Model-Driven Development)、略してCMDDと呼ぶことにします。</p><section><h2>ビジネス・モデリングの位置付け</h2><p>まず最初の作業分野はビジネス・モデリングです。</p><p>ビジネス・モデリングの関心分野の候補としては、カスタマー(Customer)とソルーション(Solution)が考えられます。</p><p>Essenceカーネルではカスタマーには以下のアルファが定義されています。</p><ul><li>ステークホルダー(Stakeholders)</li><li>機会(Opportunity)</li></ul><p>またソルーションには以下のアルファが定義されています。</p><ul><li>要求(Requirements)</li><li>ソフトウェア・システム(Software System)</li></ul><p>ビジネス・モデリングをどの関心分野のどのアルファにどのような形で組み込むかは、開発プロセス内でのビジネス・モデリングの目的によって変わってくるところでしょう。</p><p>CMDDでは小規模チームで、中小規模アプリケーションまたは大規模アプリケーションのサブシステムの開発をターゲットにします。</p><p>ビジネス・モデリングは要求アルファの入力の情報になるものなので、ソルーションの補助的な活動と考えると要求アルファにアクティビティと成果物を追加するアプローチも考えられます。</p><p>また、ビジネス・モデリングはソルーションの外側、カスタマー側の情報と考えるとカスタマー側に配置することも考えられます。その場合はステークホルダー、機会といったアルファに入れるよりも、新しくビジネス・モデリングを行うアルファを追加するのがよさそうです。</p><p>今回は関心分野カスタマーに新規のアルファとしてビジネス・システム・アルファを追加して検討を進めることにします。</p></section><section><h2>ビジネス・システム・アルファ</h2><p>ビジネス・モデリングではビジネス・システムをモデリングします。</p><p>このビジネス・システムをモデリングするアルファをビジネス・システム・アルファとします。ビジネス・システム・アルファの成果物(Work Product)として以下のモデルを考えます。具体的なモデルを作ってみて調整していく予定です。</p><ul><li>ビジョン</li><li>ビジネス・コンテキスト</li><li>ビジネス・ユースケース</li><li>ドメイン・モデル</li></ul><section><h3>ビジョン</h3><p>ビジョン(Vision)はプロジェクトのビジネス・システム上のビジョンです。</p><p>プロジェクトの全体の方向性を定めます。</p><p>このビジョンをベースに、要求アルファでソフトウェア開発上のビジョンを定める想定です。</p></section><section><h3>ビジネス・コンテキスト</h3><p>ビジネス・システムのおかれている環境をビジネス・コンテキストとしてモデル化します。</p><p>ビジネス・システムと関係する外部組織の存在とインタラクションを明確にします。</p></section><section><h3>ビジネス・ユースケース</h3><p>ビジネス・ユースケース(Business UseCase)はビジネス・システムにおけるユースケースです。</p><p>ビジネス・コンテキストの舞台の上で、ビジネス・システムの各種利用者が体験する物語を記述します。</p><p>開発対象のソフトウェア・システムはこの物語の中に登場し、物語の遂行を助けます。</p><p>要求アルファで作成する(システム)ユースケースは、ビジネス・ユースケースの物語の中での利用方法を切り口に・ソフトウェア・システムと利用者の対話の物語を記述することになります。</p></section><section><h3>ドメイン・モデル</h3><p>ドメイン・モデル(Domain Model)はソフトウェア・システムの操作対象となる問題領域(problem domain)のモデルです。</p><p>ドメイン・モデルはビジネス・システムとソフトウェア・システムで一本化したいので、その方向で検討を進めます。</p><p>ただ、ビジネス・システムとソフトウェア・システムのモデルの規模が違いすぎる場合は別立てで管理した方がよいかもしれません。そのあたりの考察も進めていきたいと思います。</p></section></section><section><h2>まとめ</h2><p>今回は要求アルファの入力となるビジネス・モデリングの扱いについて考えてみました。</p><p>ここでは、関心分野カスタマー側にビジネス・システム・アルファとして入れることにしましたが、その是非は今後の考察で検討していきたいと思います。</p><p>次回は、ビジネス・システム・アルファの具体的な検討に入る前に、モデルなどの成果物の管理方法について検討します。</p></section></div>
asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-56218912587361721192024-01-31T18:00:00.002+09:002024-01-31T18:00:00.143+09:00Cozyによるモデル駆動開発<div><p>モデル駆動開発のエコシステムを支えるキーパーツとして、Webアプリケーション・フレームワークのCozy Webを開発してきました。</p><p>今回からCozyを使用したモデル駆動開発について具体的に考えていきたいと思います。</p><p>Cozyは現在開発途中ですが、モデル駆動開発に必要な機能を拡張していく上でどのような機能が必要かの洗い出しが目的です。要求モデルにおけるユースケース分析的なアプローチですね。</p><p>EssenceというOMGが標準化している開発方法論フレームワークの枠組み、用語を使用して考えていくことにします。</p><p>実際の検討に入る前に、今回は開発方法論を記述する言語として使用するEssenceについてみていきます。</p><section><h2>Essence</h2><p>Essenceは<a href="http://semat.org/">Software Engineering Methods and Theory</a>と<a href="https://www.omg.org/">Object Management Group®</a>によって作成された開発方法論のフレームワークです。</p><ul><li>https://www.omg.org/spec/Essence/</li></ul><p>Essenceでは開発方法論を記述する言語(Language)と基本的な枠組み(Kernel)を定めており、この骨組みにプラクティスで肉付けすることで開発方法論を定義します。</p><p>Essenceの言語では、従来のモデリングの用語に加えて、新しい用語が導入されています。その点も含めて用語の整理をします。</p></section><section><h2>基本概念</h2><section><h3>アルファ</h3><p>アルファ(alpha)は開発作業を進める上で必要な各種概念を表現したものです。アルファの具体例として要求(requirement)やソフトウェア・システム(software system)があります。</p><p>アルファに対応する日本語用語はないと思うので、本Blogではアルファの用語を使います。</p></section><section><h3>ワーク・プロダクト</h3><p>ワーク・プロダクト(work product)はソフトウェア開発の各種成果物です。</p><p>ワーク・プロダクトの例としては要求仕様(要求アルファ)やコード(ソフトウェア・システム・アルファ)があります。</p></section><section><h3>アクティビティ</h3><p>アクティビティ(activity)はソフトウェア開発の活動を表現します。</p><p>アクティビティの例としては「ミーティングを開く(Holding a meeting)や「コードを書く(Writing Code)」があります。</p></section><section><h3>アクティビティ・スペース</h3><p>アクティビティ・スペース(activity space)はソフトウェア開発の活動分野を表現したものです。</p><p>アクティビティ・スペース内でアクティビティが実行されます。</p><p>アクティビティ・スペースの例としては「ステークホルダー・ニーズを理解する」や「システムを実装する」などがあります。</p></section><section><h3>コンピテンシィ</h3><p>コンピテンシィ(competency)は作業を進めるのに必要な各種能力です。</p><p>コンピテンシィの具体例としてはステークホルダー代表(カスタマー関心分野)や開発(ソルーション関心分野)などがあります。</p></section></section><section><h2>関心分野</h2><p>Essenceではソフトウェア開発の関心分野(area of concern)として以下の3つを定義しています。</p><ul><li>カスタマー</li><li>ソルーション</li><li>エンデバー</li></ul><p>Essenceのアクティビティはこの関心分野のどれかに所属することになります。</p><section><h3>カスタマー</h3><p>カスタマー(customer)はソフトぅエア・システムの利用方法についての関心分野です。</p><p>Essenceカーネルではカスタマーの関心分野で以下のアルファを定義しています。</p><ul><li>ステークホルダー (stakeholder)</li><li>機会 (opportunity)</li></ul><p>また以下のアクティビティ・スペースを定義しています。</p><ul><li>可能性を探る (Explore Possibilities)</li><li>ステークホルダー・ニーズを理解する (Understand Stakeholder Needs)</li><li>ステークホルダーの満足を確保する (Ensure Stakeholder Satisfaction)</li><li>システムを利用する (Use the System)</li></ul></section><section><h3>ソリューション</h3><p>ソルーション(solution)はソフトウェアの実現に関しての関心分野です。</p><p>Essenceカーネルではソルーションの関心分野で以下のアルファを定義しています。</p><ul><li>要求 (requirement)</li><li>ソフトウェア・システム (software system)</li></ul><p>また以下のアクティビティ・スペースを定義しています。</p><ul><li>要求を理解する (Understand the Requirements)</li><li>システムを形作る (Shape the System)</li><li>システムを実装する (Implement the System)</li><li>システムをテストする (Test the System)</li><li>システムを配備する (Deploy the System)</li><li>システムを運用する (Operate the System)</li></ul></section><section><h3>エンデバー</h3><p>エンデバー(endevor)は直訳すると「努力」ですが、ここではチームが努力して進める活動というような意味合いから選ばれた用語ではないかと思います。</p><p>エンデバーに対応する日本語用語はないと思うので、本Blogではエンデバーの用語を使います。</p><p>Essenceカーネルではソルーションの関心分野で以下のアルファを定義しています。</p><ul><li>チーム (team)</li><li>ワーク (work)</li><li>仕事の進め方 (way of working)</li></ul><p>また以下のアクティビティ・スペースを定義しています。</p><ul><li>ワークの準備をする (Prepare to do the Work)</li><li>アクティビティを協調させる (Coordinate Activity)</li><li>チームをサポートする (Support the Team)</li><li>進捗を追尾する (Track Progress)</li><li>ワークを止める (Stop the Work)</li></ul></section></section><section><h2>まとめ</h2><p>本ブログでCozyを使用したモデル駆動開発に対する分析を始めることにしました。</p><p>開発プロセスを記述するためのフレームワークとしてOMGのEssenceを使用します。今回はその準備としてEssenceの用語の整理をしました。</p><p>次回はビジネス・モデリングんいついて考えます。</p></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-1974478199763844402023-12-31T18:00:00.002+09:002023-12-31T18:00:00.139+09:00Cozy Web/グリッド内カードのカスタマイズ<div><p>モデル駆動開発のエコシステムのキーパーツとして、Webアプリケーション・フレームワークのCozy Webを紹介しています。</p><p>前回はWebフロントエンド・フレームワークBootstrapの上でグリッド表示を行いました。</p><p>今回はグリッド内に配置されるカードをカスタマイズする方法について説明します。</p><section><h2>HelloGrid</h2><p>前回作成したリソースのグリッド表示を行うHelloGridを使用します。</p><p>HelloGridはBootstrap 5を使ってグリッド表示を行います。</p><p><a href="https://modegramming.blogspot.com/2022/08/cozy-webweb.html">Cozy Web/Webライブラリ</a>で紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用しています。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloGridを作成します。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義します。これはHelloResourceと同じ設定です。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しており、Webのリソースproductとなります。</p></section><section><h3>webapp.conf</h3><p>ホームディレクトリのWEB-INFディレクトリ配下にwebapp.confを配置し、Bootstrap5ライブラリの名前である「bootstrap5」をextend属性に設定します。この設定を行うことで、Bootstrap5ライブラリがWebアプリケーションのベースとして設定されます。</p><p>またthemeにbootstrap-gridを設定します。この設定により一覧表示がグリッドで表示されます。</p><p>ここまでが前回の設定です。</p><pre class="java" name="code">extend: bootstrap5
theme: bootstrap-grid
</pre><p>今回はグリッドの表示方法をカスタマイズします。</p><p>このためにwebapp.confに以下のようにrender.card_kind_in_gridを設定します。</p><p>render.card_kind_in_gridに"grid"を指定しているので、card__gridという名前のウィジェットがグリッド内のカードの表示に使用されます。</p><pre class="java" name="code">extend: bootstrap5
theme: bootstrap-grid
render.card_kind_in_grid: "grid"
</pre></section><section><h3>カードの表示内容の設定</h3><p>グリッド内にカードを表示するときに使用するウィジェットcard_gridを作成します。</p><p>以下のJade形式の card__grid.jade 作成し、WEB-INF/widgets配下に配置します。</p><pre class="java" name="code">-@val card: ViewCard
div.card
div.card-header
h4.card-title
=card.header
</pre><p>ファイル名card__grid.jadeの「card」はウィジェット種別を表しこの場合はカードを示します。「__」の後のgridはウィジェットの名前を表します。</p><p>カードを記述するDIV要素以下をカードの部品として定義しています。部品内ではHTMLの要素を自由に使うことができます。</p><p>部品内のHTML要素ではBootstrapで定義されているcard, card-header, card-titleといったクラス属性を指定しているので、Bootstrapによって適切な表示が行われます。</p><p>また、カードの表示に必要な情報はViewCardオブジェクトとして渡されてくるので、ここから必要な情報を取り出してウィジェット内のHTML要素に埋め込んでいきます。ここではカードのヘッダ情報をH4要素に入れています。</p></section></section><section><h2>グリッド表示</h2><p>それでは、グリッド表示を行います。</p><section><h3>Webブラウザ</h3><p>productリソースに対するアクセスを行います。</p><pre class="java" name="code">http://localhost:8080/web/HelloGrid/product
</pre><p>webページの表示のために出力されたHTML文書は以下になります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css"/>
<style>
.card a {
color: inherit;
text-decoration: none;
}
.card:hover {
background-color: #f8f9fa;
border-color: #007bff;
}
</style>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<div class="card-header">
<h4 class="card-title">
Apple
</h4>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<div class="card-header">
<h4 class="card-title">
Orange
</h4>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<div class="card-header">
<h4 class="card-title">
Peach
</h4>
</div>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<div class="card-header">
<h4 class="card-title">
Berry
</h4>
</div>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</body>
</html>
</pre><p>前回のグリッド表示ではカード部分は以下のHTML断片になっていました。</p><pre class="java" name="code"> <div class="card">
<a href="product/1.html" class="">
<img src="assets/img/no-image-icon.png" class="card-img-top"/>
<div class="card-header">
<h4 class="card-title">Apple</h4>
</div>
</a>
</div>
</pre><p>今回は、以下のHTML断片になっており、グリッド内のカードはcard__grid.jadeで定義したものが使用されています。</p><pre class="java" name="code"> <div class="card">
<div class="card-header">
<h4 class="card-title">
Apple
</h4>
</div>
</div>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Webでリソースの定義をすることで、Webアプリケーションが簡単に作成できることを確認してきました。</p><p>今回はBootstrapによるレスポンシブル・デザインによるグリッド表示のカードをカスタマイズする方法について説明しました。</p><p>モデルの定義とカスタマイズしたカードの定義以外はほとんどノープログラミングでレスポンシブルなWebアプリケーションの作成ができることを確認することができました。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.16</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-59305713915652716002023-11-30T18:00:00.016+09:002023-11-30T18:00:00.135+09:00Cozy Web/グリッド<div><p>モデル駆動開発のエコシステムのキーパーツとして、Webアプリケーション・フレームワークのCozy Webを紹介しています。</p><p>数回に渡りリソースの一覧表示の方法について見てきました。その一環でグリッドとカードによる一覧表示を取り上げます。グリッドとカードによる覧表表示はHTMLの標準機能では用意されていないので、この機能をサポートしているWebフロントエンド・フレームワークBootstrapを導入し、その上でグリッドとカードによるリソースの一覧表示を行うことにします。</p><section><h2>HelloGrid</h2><p>リソースのグリッド表示を行うHelloGridを作成します。</p><p>HelloGridはBootstrap 5を使ってグリッド表示を行います。</p><p><a href="https://modegramming.blogspot.com/2022/08/cozy-webweb.html">Cozy Web/Webライブラリ</a>で紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用します。<a href="https://modegramming.blogspot.com/2022/08/cozy-webweb.html">Cozy Web/Webライブラリ</a>で紹介したWebライブラリ機能を使用してBootstrap 5をサポートするBootstrap5ライブラリを使用します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloGridを作成します。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義します。これは前回まで使用していたHelloResourceと同じ設定です。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しており、Webのリソースproductとなります。</p></section><section><h3>webapp.conf</h3><p>ホームディレクトリのWEB-INFディレクトリ配下にwebapp.confを配置し、Bootstrap5ライブラリの名前である「bootstrap5」をextend属性に設定します。この設定を行うことで、Bootstrap5ライブラリがWebアプリケーションのベースとして設定されます。</p><pre class="java" name="code">extend: bootstrap5
</pre></section></section><section><h2>一覧表示</h2><p>CozyのWebライブラリBootstrap5はデフォルトでは、tableタグを使った一覧表示を行います。</p><section><h3>Webブラウザ</h3><p>前回と同様にproductリソースに対するアクセスを行います。</p><pre class="java" name="code">http://localhost:8080/web/HelloGrid/product
</pre>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgQurCuX0MplA3yUctxlNk9a7X91MCzFqfWk_E4KJFqVFB5TtVEUBgUykQP2VOI-mUSsWjSuSjbYpWVLK0f9XqTiKepx5rntn-mfrevKfNaWOrlhVM_67UMaVoJedUmLWcw3gNHXtpaVMeSEY1K7_FPyvEdiusckrVzBNBdeTB8kpbEMWTuhwUtRpzNi8/s1880/product_list.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="956" data-original-width="1880" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhgQurCuX0MplA3yUctxlNk9a7X91MCzFqfWk_E4KJFqVFB5TtVEUBgUykQP2VOI-mUSsWjSuSjbYpWVLK0f9XqTiKepx5rntn-mfrevKfNaWOrlhVM_67UMaVoJedUmLWcw3gNHXtpaVMeSEY1K7_FPyvEdiusckrVzBNBdeTB8kpbEMWTuhwUtRpzNi8/s320/product_list.png"/></a></div>
<p><a href="https://modegramming.blogspot.com/2022/08/cozy-webweb.html">Cozy Web/Webライブラリ</a>で説明したとおり、WebライブラリBootstrapでは、ナビゲーションバーやヘッダー、フッターを使用した画面レイアウトになります。<a href="https://modegramming.blogspot.com/2022/08/cozy-webweb.html">Cozy Web/Webライブラリ</a>で説明したとおり、WebライブラリBootstrapでは、ナビゲーションバーやヘッダー、フッターを使用した画面レイアウトになります。</p><p>画面内のコンテンツの部分にBootstrapによって綺麗にレイアウトされた表が表示されました。</p></section><section><h3>HTML</h3><p>webページの表示のために出力されたHTMLは以下になります。</p><p>tableタグにはBootstrap用のclass属性が設定されているため、Bootstrap標準の綺麗な表が出力されます。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
<style>
.card a {
color: inherit;
text-decoration: none;
}
.card:hover {
background-color: #f8f9fa;
border-color: #007bff;
}
</style>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="table-responsive">
<table class="table">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th class="" scope="col">Id</th>
<th class="" scope="col">Name</th>
<th class="" scope="col">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/4.html">
<td class="">4</td>
<td class="">Berry</td>
<td class="">450</td>
</tr>
</tbody>
</table>
</div>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</body>
</html>
</pre></section></section><section><h2>グリッド</h2><p>それでは、グリッド表示を行います。</p><section><h3>webapp.conf</h3><p>Bootstrapアプリケーションの一覧表示のデフォルト設定をwebapp.confに設定することができます。</p><p>webapp.confのthemeにテーマbootstrap-gridを設定します。</p><p>テーマbootstrap-gridは一覧表示のデフォルト設定をグリッドにしたテーマです。</p><pre class="java" name="code">extend: bootstrap5
theme: bootstrap-grid
</pre></section><section><h3>Webブラウザ</h3><p>productリソースに対するアクセスを行います。</p><pre class="java" name="code">http://localhost:8080/web/HelloGrid/product
</pre><p>表示結果は以下になります。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid32v7iu5sKzghPpCbQ2T9dn_LvkCyodoWqa5fuHg-2dRwq9R1rWdlAhU63UuI7UOFc9j-KEl-v_SMncza3G6cJ6JWZoy_FQTT1DrJBCfszEOEXawH8w8TZV8KSHdKbVIdZoA9lxF5DX96qdU2Bt8oMy6yUgaozv5kVE645YNPotrpAnuW-G72kWSFpuU/s2118/product_grid.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="786" data-original-width="2118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEid32v7iu5sKzghPpCbQ2T9dn_LvkCyodoWqa5fuHg-2dRwq9R1rWdlAhU63UuI7UOFc9j-KEl-v_SMncza3G6cJ6JWZoy_FQTT1DrJBCfszEOEXawH8w8TZV8KSHdKbVIdZoA9lxF5DX96qdU2Bt8oMy6yUgaozv5kVE645YNPotrpAnuW-G72kWSFpuU/s320/product_grid.png"/></a></div>
<p>無事Bootstrapのグリッド表示になります。グリッド内にはリソースの内容を記述するカードが表示されています。</p><p>デフォルトでは、カード内にはリソースの内容を表す画像どリソースの名前が表示されます。productでは画像の情報は持っていないので、画像なしを示す画像が表示されています。</p><p>Bootstrapのグリッドは画面サイズを変えても適切にレイアウトが行われます。先ほどのWebページの横幅を小さく縮めたWebページが以下になります。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNCVImSE-SHIx2SkUGJFrNFA8CV3xW6yjQZ15yyp0E95E0b3vNAb-nQy-phlWUp9_thS0jUDjwkbaCM6EPYIYCqzUrC_M3JxrUE6SE-LhQyFPcnftRSeKVd8u1HYGRof-_i8eXpHRnTB9ooHsv3Uk54YjKYv2E_bC_d7MSz9qSlIJK2gO5Es_Fdh5OtUA/s1518/product_grid_narrow.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" height="320" data-original-height="1518" data-original-width="1322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiNCVImSE-SHIx2SkUGJFrNFA8CV3xW6yjQZ15yyp0E95E0b3vNAb-nQy-phlWUp9_thS0jUDjwkbaCM6EPYIYCqzUrC_M3JxrUE6SE-LhQyFPcnftRSeKVd8u1HYGRof-_i8eXpHRnTB9ooHsv3Uk54YjKYv2E_bC_d7MSz9qSlIJK2gO5Es_Fdh5OtUA/s320/product_grid_narrow.png"/></a></div>
</section><section><h3>HTML</h3><p>webページの表示のために出力されたHTMLは以下になります。</p><p>グリッド内のカードはclass属性にcardが設定されたdevタグで記述されています。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<meta content="width=device-width, initial-scale=1" name="viewport"/>
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"/>
<style>
.card a {
color: inherit;
text-decoration: none;
}
.card:hover {
background-color: #f8f9fa;
border-color: #007bff;
}
</style>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"/>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<a href="product/1.html" class="">
<img src="assets/img/no-image-icon.png" class="card-img-top"/>
<div class="card-header">
<h4 class="card-title">Apple</h4>
</div>
</a>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<a href="product/2.html" class="">
<img src="assets/img/no-image-icon.png" class="card-img-top"/>
<div class="card-header">
<h4 class="card-title">Orange</h4>
</div>
</a>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<a href="product/3.html" class="">
<img src="assets/img/no-image-icon.png" class="card-img-top"/>
<div class="card-header">
<h4 class="card-title">Peach</h4>
</div>
</a>
</div>
</div>
<div class="col-12 col-sm-6 col-md-3 col-lg-2 col-xl-1">
<div class="card">
<a href="product/4.html" class="">
<img src="assets/img/no-image-icon.png" class="card-img-top"/>
<div class="card-header">
<h4 class="card-title">Berry</h4>
</div>
</a>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>前回まではCozy Webでリソースの定義をすることで、Webアプリケーションが簡単に作成できることを説明しました。</p><p>今回は画面の表示方法のカスタマイズとして、グリッド表示を取り上げました。</p><p>テーマの設定のみで一覧表示をtableタグによる表からBootstrapならではのグリッド表示にすることができました。また、グリッド表示はBootstrapの機能により画面サイズに従って適切なレイアウトが行われることが確認できました。</p><p>モデルの定義以外はほとんどノープログラミングでWebアプリケーションの作成ができることが分かりました。</p><p>次回はグリッド表示のカスタマイズ方法について取り上げる予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.15</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-83446582031899832962023-10-31T18:00:00.001+09:002023-10-31T18:00:00.138+09:00<div><p>Cozy Web上でエンティティのモデル定義によって設定されたリソースの一覧アクセスをノンプログラミングで行う方法についてみています。</p><p>前回はリソースの一覧表示の機能機能について説明します。</p><p>今回はページング機能について説明します。</p><section><h2>HelloResource</h2><p>リソースの作成・更新処理の題材としてHelloResourceを定義しました。</p><p>このHelloResourceを使用して、リソースの一覧表示の方法についてみています。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてホームディレクトリに以下のindex.htmlを配備しています。これは前回と同様です。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
<li><a href="product/_delete_">Delete</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>一覧表示</h2><p>まず、前回紹介したパラメタなしの場合です。</p><p>以下のようにリソース名を指定してアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>その結果、以下のページが表示されます。(この結果はxmllintで整形しています。他のHTML出力も同様です。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<div>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>Prev</td>
<td>
<a href="#?query.offset=0&amp;query.page.size=1">1</a>
</td>
<td>
<a href="#?query.offset=1&amp;query.page.size=1">2</a>
</td>
<td>
<a href="#?query.offset=2&amp;query.page.size=1">3</a>
</td>
<td>
<a href="#?query.offset=3&amp;query.page.size=1">4</a>
</td>
<td>Next</td>
</tr>
</table>
</div>
</body>
</html>
</pre></section><section><h2>ページング</h2><p>次はページング機能を使用してみます。</p><p>ページング機能を使用する場合、query.page.sizeパラメタで1ページ数あたりの行数を指定します。</p><p>以下のようにリソース名のページを指定して、queyr.page.sizeに「1」を指定して実行してみます。</p><pre class="java" name="code">$ curl "http://localhost:8080/web/HelloResource/product?query.page.size=1"
</pre><p>この結果、以下のページが表示されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<div>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>Prev</td>
<td>
<a href="#?query.offset=0&amp;query.page.size=1">1</a>
</td>
<td>
<a href="#?query.offset=1&amp;query.page.size=1">2</a>
</td>
<td>
<a href="#?query.offset=2&amp;query.page.size=1">3</a>
</td>
<td>
<a href="#?query.offset=3&amp;query.page.size=1">4</a>
</td>
<td>Next</td>
</tr>
</table>
</div>
</body>
</html>
</pre><p>query.page.sizeに「1」を指定しているので1ページあたり1行表示のページングが行われています。データ表示のテーブルの下部にページング移動用のテーブルが表示されています。全レコード数が4なので、4ページの構成となっています。</p></section><section><h2>まとめ</h2><p>今回はリソースの一覧表示のページングについて説明しました。</p><p>次回はカスタム画面などの機能について説明する予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.15</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-58447579077090779462023-09-30T19:00:00.004+09:002023-09-30T19:00:00.146+09:00Cozy Web/一覧表示<div><p>Cozy Web上でエンティティのモデル定義によって設定されたリソースの一覧アクセスをノンプログラミングで行う方法についてみていきます。</p><p>今回はリソースの一覧表示の機能機能について説明します。</p><section><h2>HelloResource</h2><p>リソースの作成・更新処理の題材としてHelloResourceを定義しました。</p><p>今回からこのHelloResourceを使用して、リソースの一覧表示の方法についてみていきます。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてホームディレクトリに以下のindex.htmlを配備しています。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
<li><a href="product/_delete_">Delete</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>リソース一覧のシナリオ</h2><p>リソースの作成・更新では入力フォームの入力から始まるシナリオによって、複数の画面によって作成・更新処理を実行しました。</p><p>一方、リソース一覧では一覧表示したいリソースの名前と表示方法を指定するパラメタを渡すことで、すぐに表示結果を得ることができます。</p></section><section><h2>実行</h2><p>それではリソース一覧の表示を行ってみましょう。</p><section><h3>一覧表示</h3><p>まず、パラメタなしの場合です。</p><p>以下のようにリソース名を指定してアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>その結果、以下のページが表示されました。(この結果はxmllintで整形しています。他のHTML出力も同様です。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section><section><h3>範囲指定</h3><p>query.offsetパラメタで開始オフセットを、query.limitパラメタで表示の範囲を指定することができます。</p><p>以下の例ではquery.offsetに1、query.limitに1を指定しているので、2番目のレコードから1レコードを表示します。</p><pre class="java" name="code">$ curl "http://localhost:8080/web/HelloResource/product?query.offset=1&query.limit=1"
</pre><p>実行の結果、以下のようにレコード数1の表が表示されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section><section><h3>カラム指定</h3><p>query.columnsパラメタで表示するカラムを指定することができます。</p><p>以下の例ではquery.columnsに「name,price」を指定しているのでnameとpriceの2カラムの表を表示します。</p><pre class="java" name="code">$ curl "http://localhost:8080/web/HelloResource/product?query.columns=name,price"
</pre><p>実行の結果、以下のように2カラムの表が表示されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>今回はリソースの一覧表示の基本機能について説明しました。</p><p>次回はページングやカスタム画面などの機能について説明する予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.14</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-2597996855959408812023-08-31T18:00:00.003+09:002023-08-31T18:00:00.151+09:00Cozy Web/エンティティ削除<div><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>ここまでエンティティの作成、更新の方法について説明しました。</p><p>モデルを定義するだけで、エンティティの作成・更新画面が自動的に提供されることを確認しました。それぞれの画面ではエンティティ成・更新を入力、確認、表示の3画面を使って行うことができました。また、エンティティの作成・更新画面のカスタム画面を定義することも可能になっています。</p><p>今回はエンティティの削除について説明します。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成と更新を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。</p><p>今回は削除処理のアプリケーション定義ビューを追加します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてホームディレクトリに以下のindex.htmlを配備しています。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
<li><a href="product/_delete_">Delete</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>エンティティ操作シナリオ</h2><p>エンティティのモデル定義を行うとエンティティ作成シナリオ、更新シナリオに加えて削除シナリオが自動的に作成されます。</p><p>エンティティの削除には以下の2種類があります。</p><ul><li>更新するエンティティのIDを削除画面から入力</li><li>更新するエンティティのIDを削除開始時に指定</li></ul></section><section><h2>実行</h2><p>それではエンティティの削除を実行してみましょう。まず削除するIDを削除画面から入力する方式です。</p><section><h3>エンティティ削除ページ</h3><p>以下のようにリソース名の後ろに「_delete_」をつけてアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/_delete_
</pre><p>次のようにエンティティ削除に必要なIDを指定するためのFORMの画面が表示されました。</p><p>ビューの定義はしていないので、Cozy Webのデフォルト入力画面が表示されます。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">
<input type="text" name="id" value=""/>
</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Input"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
</form>
</body>
</html>
</pre><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>エンティティ削除</dd><dt>Cancel</dt><dd>キャンセル Inputボタンを押下するとエンティティ削除のための次の画面に遷移します。</dd></dl><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>削除確認ページ</h3><p>エンティティ削除ページでInputボタンが押されたので、削除確認画面が表示されます。</p><pre class="java" name="code"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">300</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
</form>
</body>
</html>
</pre><p>画面に削除予定のエンティティのデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>OK</dt><dd>確認OK</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Okボタンを押下するとエンティティの削除を行い、その結果を表示する画面に遷移します。</p></section><section><h3>結果ページ</h3><p>削除確認画面でOKボタンが押されたので、エンティティの削除が行われ、削除されたエンティティの情報表示ページに移ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">100</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="1"/>
<input type="hidden" name="name" value="Apple"/>
<input type="hidden" name="price" value="100"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
</form>
</body>
</html>
</pre><p>削除したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li>
<a href="product">List</a>
</li>
<li>
<a href="product/_create_">Create</a>
</li>
<li>
<a href="product/_update_">Update</a>
</li>
<li>
<a href="product/_delete_">Delete</a>
</li>
</ul>
</body>
</html>
</pre></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のようにオブジェクトID 1のAppleが削除されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/4.html">
<td class="">4</td>
<td class="">Banana</td>
<td class="">250</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>実行/ID指定</h2><p>続けてIDを指定したエンティティの更新を実行してみましょう。</p><section><h3>エンティティ更新ページ</h3><p>IDを指定してリエンティティの更新を行ってみます。IDが1の場合は以下になります。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/1/_delete_
</pre></section><section><h3>削除確認ページ</h3><p>エンティティ削除ページでInputボタンが押されたので、削除確認画面が表示されます。</p><pre class="java" name="code"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">300</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
</form>
</body>
</html>
</pre><p>画面に削除予定のエンティティのデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>OK</dt><dd>確認OK</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Okボタンを押下するとエンティティの削除を行い、その結果を表示する画面に遷移します。</p></section><section><h3>結果ページ</h3><p>削除確認画面でOKボタンが押されたので、エンティティの削除が行われ、削除されたエンティティの情報表示ページに移ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">100</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="1"/>
<input type="hidden" name="name" value="Apple"/>
<input type="hidden" name="price" value="100"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
</form>
</body>
</html>
</pre><p>削除したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li>
<a href="product">List</a>
</li>
<li>
<a href="product/_create_">Create</a>
</li>
<li>
<a href="product/_update_">Update</a>
</li>
<li>
<a href="product/_delete_">Delete</a>
</li>
</ul>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Webでのエンティティの削除の方法について説明しました。モデルの定義のみでシナリオに沿ったエンティティの更新、作成、削除ができることが分かりました。</p><p>次回からエンティティの一覧表示について見ていきます。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.14</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-56697093174293876562023-07-31T18:00:00.001+09:002023-07-31T18:00:00.141+09:00Cozy Web/エンティティ更新のカスタム画面<div><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>前回はエンティティ更新の方法について説明しました。</p><p>モデルを定義するだけで、エンティティの更新画面が自動的に提供されることを確認しました。エンティティ更新を入力、確認、表示の3画面を使って行うことができました。</p><p>前回は、画面そのものはCozyが作成したデフォルト画面です。今回はエンティティ更新のカスタム画面を設定する方法について説明します。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成と更新を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。</p><p>今回は更新処理のアプリケーション定義ビューを追加します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてホームディレクトリに以下のindex.htmlを配備しています。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>エンティティ操作シナリオ</h2><p>エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。</p><p>エンティティの更新には以下の2種類があります。</p><ul><li>更新するエンティティのIDを更新画面から入力</li><li>更新するエンティティのIDを更新開始時に指定</li></ul></section><section><h2>アプリケーション定義ビュー</h2><p>エンティティの更新シナリオの3つの処理、入力処理、確認処理、表示処理それぞれのアプリケーションのカスタム画面をみていきます。</p><section><h3>入力画面</h3><p>カスタムの入力画面として以下のupdate__input.htmlをproduct.entityディレクトリに配備します。</p><pre class="java" name="code"><html>
<head>
<title>Update Product/Input</title>
</head>
<body>
<h1>Update Product/Input</h1>
<c:detail />
</body>
</html>
</pre><p>タグ c:detail の場所に入力処理用の入力フォームが出力されます。</p><p>デフォルト画面との変更点はヘッダと画面のタイトル部を追加している点です。ここではシンプルな追加のみにしていますが、必要に応じて画面のデザインを追加していく形になります。</p></section><section><h3>確認画面</h3><p>カスタムの入力画面として以下のupdate__confirm.htmlをproduct.entityディレクトリに配備します。</p><pre class="java" name="code"><html>
<head>
<title>Update Product/Confirm</title>
</head>
<body>
<h1>Update Product/Confirm</h1>
<c:detail />
</body>
</html>
</pre><p>タグ c:detail の場所に確認処理用のフォームが出力されます。</p><p>入力画面と同様に、変更点はヘッダと画面のタイトル部を追加している点です。</p></section><section><h3>表示画面</h3><p>カスタムの入力画面として以下のupdate__show.htmlをproduct.entityディレクトリに配備します。</p><pre class="java" name="code"><html>
<head>
<title>Update Product/Show</title>
</head>
<body>
<h1>Update Product/Show</h1>
<c:detail />
</body>
</html>
</pre><p>タグ c:detail の場所に結果確認処理用のフォームが出力されます。</p><p>入力画面や確認画面と同様に、変更点はヘッダと画面のタイトル部を追加している点です。</p></section></section><section><h2>実行</h2><p>それではIDを指定したエンティティの更新を実行してみましょう。</p><section><h3>エンティティ更新ページ</h3><p>IDを指定してリエンティティの更新を行ってみます。IDが1の場合は以下になります。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/1/_update_
</pre><p>次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。</p><p>update__input.htmlとして登録した入力ページが表示されました。</p><p>画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Update Product/Input</title>
</head><body>
<h1>Update Product/Input</h1>
<form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class=""><input type="text" name="id" value="1" /></td></tr><tr class=""><th scope="row" class="">Name</th><td class=""><input type="text" name="name" value="Apple" /></td></tr><tr class=""><th scope="row" class="">Price</th><td class=""><input type="text" name="price" value="300" /></td></tr></tbody>
</table>
<table>
<tr><td><input type="submit" name="$submit" value="Input" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{},&quot;id&quot;:&quot;1&quot;}" />
</form>
</body></html>
</pre><p>作成の場合と違って、FORMの中にID「1」の情報が動的的に設定されています。</p><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>データ登録</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>ID 1のデータはAppleですが、値段を100円から150円に変更しましょう。</p><p>Inputボタンを押下するとエンティティ更新のための次の画面に遷移します。</p><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>登録データ確認ページ</h3><p>データ登録画面でInputボタンを押すと、登録データ確認画面が表示されます。</p><p>update__confirm.htmlとして登録した入力ページが表示されました。</p><p>画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Update Product/Confirm</title>
</head><body>
<h1>Update Product/Confirm</h1>
<form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
</table>
<input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
<table>
<tr><td><input type="submit" name="$submit" value="Ok" /></td><td><input type="submit" name="$submit" value="Ok_show" /></td><td><input type="submit" name="$submit" value="Back" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Input&quot;},&quot;id&quot;:&quot;1&quot;}" />
</form>
</body></html>
</pre><p>画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>Ok</dt><dd>確認OK</dd><dt>Ok_show</dt><dd>確認OKで結果を表示</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Ok_showボタンを押下するとエンティティ更新が行われ、更新した情報の表示画面に遷移します。</p><p>Okの場合は、エンティティ更新後トップページに遷移します。</p></section><section><h3>結果ページ</h3><p>更新確認画面でOK_showボタンを押すと、エンティティの更新が行われ、作成されたエンティティの情報表示ページに移ります。</p><p>update__show.htmlとして登録した入力ページが表示されました。</p><p>画面のタイトルとして、カスタム画面の定義が使用されていることが分かります。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Update Product/Show</title>
</head><body>
<h1>Update Product/Show</h1>
<form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
</table>
<input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
<table>
<tr><td><input type="submit" name="$submit" value="Ok" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;Apple\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{},\\\&quot;id\\\&quot;:\\\&quot;1\\\&quot;}\&quot;,\&quot;price\&quot;:\&quot;150\&quot;,\&quot;id\&quot;:\&quot;1\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Ok_show&quot;},&quot;id&quot;:&quot;1&quot;}" />
</form>
</body></html>
</pre><p>作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のようにオブジェクトID 1のAppleの値段が150に変更されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">150</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Webでのエンティティの作成、削除の方法について説明してきました。モデルの定義のみでシナリオに沿ったエンティティの作成、削除ができることが分かりました。またエンティティの作成、削除画面のカスタマイズも可能です。</p><p>次回はエンティティの削除について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.13</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-24893976277136596972023-06-30T18:00:00.001+09:002023-06-30T18:00:00.147+09:00Cozy Web/エンティティ更新(2)<div><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>ここまで、エンティティの作成についてみてきました。</p><p>前回はエンティティの更新の基本形としてエンティティIDを指定しない形を説明しました。</p><p>今回はエンティティIDを指定してエンティティの更新をする方法について説明します。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>エンティティ操作シナリオ</h2><p>エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。</p><p>エンティティの更新には以下の2種類があります。</p><ul><li>更新するエンティティのIDを更新画面から入力</li><li>更新するエンティティのIDを更新開始時に指定</li></ul><p>前回、前者の更新するエンティティのIDを更新画面から入力のシナリオを確認しました。</p><p>今回は後者の更新するエンティティのIDを更新開始時に指定を実行します。</p></section><section><h2>実行</h2><p>それではIDを指定したエンティティの更新を実行してみましょう。</p><section><h3>エンティティ更新ページ</h3><p>IDを指定してリエンティティの更新を行う場合には、リソース名の後ろに「ID/_update_」をつけてアクセスします。IDが1の場合は以下になります。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/1/_update_
</pre><p>次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。</p><p>まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="TBD" />
<meta name="description" content="TBD" />
<meta name="robots" content="noindex,nofollow" />
<meta name="author" content="TBD" />
</head><body><form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class=""><input type="text" name="id" value="1" /></td></tr><tr class=""><th scope="row" class="">Name</th><td class=""><input type="text" name="name" value="Apple" /></td></tr><tr class=""><th scope="row" class="">Price</th><td class=""><input type="text" name="price" value="100" /></td></tr></tbody>
</table>
<table>
<tr><td><input type="submit" name="$submit" value="Input" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{},&quot;id&quot;:&quot;1&quot;}" />
</form></body></html>
</pre><p>作成の場合と違って、FORMの中にID「1」の情報が動的的に設定されています。</p><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>データ登録</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>ID 1のデータはAppleですが、値段を100円から150円に変更しましょう。</p><p>Inputボタンを押下するとエンティティ更新のための次の画面に遷移します。</p><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>登録データ確認ページ</h3><p>データ登録画面でInputボタンを押すと、登録データ確認画面が表示されます。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="TBD" />
<meta name="description" content="TBD" />
<meta name="robots" content="noindex,nofollow" />
<meta name="author" content="TBD" />
</head><body><form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
</table>
<input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
<table>
<tr><td><input type="submit" name="$submit" value="Ok" /></td><td><input type="submit" name="$submit" value="Ok_show" /></td><td><input type="submit" name="$submit" value="Back" /></td><td><input type="submit" name="$submit" value="Cancel" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Input&quot;},&quot;id&quot;:&quot;1&quot;}" />
</form></body></html>
</pre><p>画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>Ok</dt><dd>確認OK</dd><dt>Ok_show</dt><dd>確認OKで結果を表示</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Ok_showボタンを押下するとエンティティ更新が行われ、更新した情報の表示画面に遷移します。</p><p>Okの場合は、エンティティ更新後トップページに遷移します。</p></section><section><h3>結果ページ</h3><p>更新確認画面でOK_showボタンを押すと、エンティティの更新が行われ、作成されたエンティティの情報表示ページに移ります。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="keywords" content="TBD" />
<meta name="description" content="TBD" />
<meta name="robots" content="noindex,nofollow" />
<meta name="author" content="TBD" />
</head><body><form action="" method="POST">
<table class="">
<tbody><tr class=""><th scope="row" class="">Id</th><td class="">1</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">Apple</td></tr><tr class=""><th scope="row" class="">Price</th><td class="">150</td></tr></tbody>
</table>
<input type="hidden" name="id" value="1" /><input type="hidden" name="name" value="Apple" /><input type="hidden" name="price" value="150" />
<table>
<tr><td><input type="submit" name="$submit" value="Ok" /></td></tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Apple&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}, {\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;Apple\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}, {\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{},\\\&quot;id\\\&quot;:\\\&quot;1\\\&quot;}\&quot;,\&quot;price\&quot;:\&quot;150\&quot;,\&quot;id\&quot;:\&quot;1\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;},\&quot;id\&quot;:\&quot;1\&quot;}&quot;,&quot;price&quot;:&quot;150&quot;,&quot;id&quot;:&quot;1&quot;,&quot;$submit&quot;:&quot;Ok_show&quot;},&quot;id&quot;:&quot;1&quot;}" />
</form></body></html>
</pre><p>作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のようにオブジェクトID 1のAppleの値段が150に変更されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">150</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>今回はエンティティ更新の方法について説明しました。</p><p>モデルを定義するだけで、エンティティの更新画面が自動的に提供されることを確認しました。エンティティ更新を入力、確認、表示の3画面を使って行うことができました。</p><p>今回は、画面そのものはCozyが作成したデフォルト画面です。次回はエンティティ更新のカスタム画面を設定する方法について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.13</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-23597391397779573972023-05-31T18:00:00.001+09:002023-05-31T18:00:00.136+09:00Cozy Web/エンティティ更新 <div><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>ここまで、エンティティの作成についてみてきました。</p><p>今回はエンティティの更新についてみていきます。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/_create_">Create</a></li>
<li><a href="product/_update_">Update</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>エンティティ操作シナリオ</h2><p>エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。</p><p>このエンティティ作成シナリオによって、エンティティの作成オペレーションが可能になったことを前々回、前回に確認しました。</p><p>エンティティの更新オペレーションも同様にエンティティ作成シナリオによって可能になります。</p><p>エンティティの更新には以下の2種類があります。</p><ul><li>更新するエンティティのIDを更新画面から入力</li><li>更新するエンティティのIDを更新開始時に指定</li></ul><p>今回は前者の更新エンティティIDを更新画面から入力するシナリオを実行します。</p></section><section><h2>実行</h2><p>それではエンティティの更新を実行してみましょう。</p><section><h3>エンティティ更新ページ</h3><p>以下のようにリソース名の後ろに「_update_」をつけてアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/_update_
</pre><p>次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。</p><p>まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">
<input type="text" name="id" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">
<input type="text" name="name" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">
<input type="text" name="price" value=""/>
</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Input"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
</form>
</body>
</html>
</pre><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>データ登録</dd><dt>Cancel</dt><dd>キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。</dd></dl><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>登録データ確認ページ</h3><p>データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。</p><pre class="java" name="code"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">300</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
</form>
</body>
</html>
</pre><p>画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>OK</dt><dd>確認OK</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Okボタンを押下するとエンティティ作成のための次の画面に遷移します。</p></section><section><h3>結果ページ</h3><p>登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">1</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Apple</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">100</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="1"/>
<input type="hidden" name="name" value="Apple"/>
<input type="hidden" name="price" value="100"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
</form>
</body>
</html>
</pre><p>作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li>
<a href="product">List</a>
</li>
<li>
<a href="product/_create_">Create</a>
</li>
<li>
<a href="product/_update_">Update</a>
</li>
</ul>
</body>
</html>
</pre></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のようにオブジェクトID 1のAppleの値段が100に変更されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">100</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/4.html">
<td class="">4</td>
<td class="">Banana</td>
<td class="">250</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>リソースの作成に続いて、今回はリソースの更新の基本形について説明しました。</p><p>次回も引き続きリソースの更新について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.13</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-12655056103948386052023-04-30T18:00:00.001+09:002023-04-30T18:00:00.150+09:00Cozy Web/エンティティ作成ビュー<div><p>Cozy Webはモデル駆動開発の基盤となるWebフレームワークです。リソースのモデルを定義することで、ノンプログラミングでWeb上のリソースをアクセスできる機能について説明を進めています。</p><p>前回はHelloResourceを用いてエンティティの作成操作を実現方法について説明しました。</p><p>エンティティのモデル定義をすることでエンティティ作成のオペレーションが可能になりましたが、エンティティ作成画面はCozy Webのデフォルト画面が使用されます。</p><p>今回はエンティティ作成用のビューを定義することで、エンティティ作成画面をカスタマイズする方法について説明します。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われているのでそのままエンティティの作成を行うことができます。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてindex.htmlを作成し、プロジェクトのトップページに配置します。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/create">Create</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>エンティティ操作シナリオ</h2><p>エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成され、このエンティティ作成シナリオによって、エンティティの作成オペレーションが可能になります。</p><p>この時、画面はエンティティ作成シナリオのデフォルトのビューが用いられます。</p><p>アプリケーションでカスタマイズした画面を使用するためには、エンティティ作成シナリオ用のビューを登録します。</p><p>エンティティ作成シナリオ用のビューの格納場所は、エンティティ名+「.entity」ディレクトリです。エンティティproductの場合は「product.entity」です。</p><p>エンティティ作成シナリオでは以下のビューを使用します。</p><ul><li>エンティティ作成</li><li>登録データ確認</li><li>結果</li></ul><p>それぞれカスタマイズした画面を登録していきます。</p><section><h3>エンティティ作成</h3><p>エンティティ作成画面として以下のHTMLを、product.entity配下に「create__input.html」という名前で作成します。</p><p>「create__input」の「create」が作成画面を、「input」が入力画面であることを示しています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product作成/入力</title>
</head>
<body>
<h1>Product作成/入力</h1>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">
<input type="text" name="id" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">
<input type="text" name="name" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">
<input type="text" name="price" value=""/>
</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Input"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value=""/>
</form>
</body>
</html>
</pre></section><section><h3>登録データ確認</h3><p>エンティティ作成の登録データ確認画面として以下のHTMLを、product.entity配下に「create__confirm.html」という名前で作成します。</p><p>「create__confirm」の「create」が作成画面を、「confirm」がデータ確認画面であることを示しています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。</p><pre class="java" name="code"><html>
<head>
<title>Product作成/データ確認</title>
</head>
<body>
<h1>Product作成/データ確認</h1>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value=""/>
</form>
</body>
</html>
</pre></section><section><h3>結果</h3><p>エンティティ作成の登録データ確認画面として以下のHTMLを、product.entity配下に「create__show.html」という名前で作成します。</p><p>「create__show」の「create」が作成画面を、「show」がデータ結果表示画面であることを示しています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product作成/データ確認</title>
</head>
<body>
<h1>Product作成/データ確認</h1>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value=""/>
</form>
</body>
</html>
</pre></section></section><section><h2>実行</h2><p>それでは実行してみましょう。</p><section><h3>エンティティ作成ページ</h3><p>最初にエンティティ作成を行うためのデータ入力ページを表示します。</p><p>以下のようにリソース名の後ろに「_create_」をつけてアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/_create_
</pre><p>次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。</p><p>product.entityにcreate__input.htmlとして登録したビューが使用されています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完しています。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product作成/入力</title>
</head>
<body>
<h1>Product作成/入力</h1>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">
<input type="text" name="id" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">
<input type="text" name="name" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">
<input type="text" name="price" value=""/>
</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Input"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
</form>
</body>
</html>
</pre><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>データ登録</dd><dt>Cancel</dt><dd>キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。</dd></dl><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>登録データ確認ページ</h3><p>データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。</p><p>product.entityにcreate__confirm.htmlとして登録したビューが使用されています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完しています。</p><pre class="java" name="code"><html>
<head>
<title>Product作成/データ確認</title>
</head>
<body>
<h1>Product作成/データ確認</h1>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
</form>
</body>
</html>
</pre><p>画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>OK</dt><dd>確認OK</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Okボタンを押下するとエンティティ作成のための次の画面に遷移します。</p></section><section><h3>結果ページ</h3><p>登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。</p><p>product.entityにcreate__show.htmlとして登録したビューが使用されています。</p><p>Input要素のvalue属性はエンティティ操作シナリオが補完しています。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;create-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
</form>
</body>
</html>
</pre><p>作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li>
<a href="product">List</a>
</li>
<li>
<a href="product/_create_">Create</a>
</li>
</ul>
</body>
</html>
</pre></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のようにカスタムのビューを使った場合も、無事リソースが追加されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/4.html">
<td class="">4</td>
<td class="">Banana</td>
<td class="">250</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>今回はリソースの作成ビューの使用方法について説明しました。</p><p>次回はリソースの更新、削除の操作の作成鳳凰について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.12</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-48003556346524789182023-03-31T18:00:00.001+09:002023-03-31T18:00:00.171+09:00Cozy Web/エンティティ作成<div><p>Cozy Webはモデル駆動開発の基盤となるWebフレームワークです。リソースのモデルを定義することで、ノンプログラミングでWeb上のリソースをアクセスできる機能について説明を進めています。</p><p>前回はHelloResourceを用いてエンティティの参照について説明しました。</p><p>今回は引き続きHelloResourceを用いてエンティティの作成について説明します。</p><section><h2>HelloResource</h2><p>ここまで作成したHelloResourceは、モデルの定義が行われているのでそのままエンティティの作成を行うことができます。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>トップページ</h3><p>トップページとしてindex.htmlを作成し、プロジェクトのトップページに配置します。</p><pre class="java" name="code"><html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li><a href="product">List</a></li>
<li><a href="product/create">Create</a></li>
</ul>
</body>
</html>
</pre></section></section><section><h2>実行</h2><p>それでは実行してみましょう。</p><section><h3>エンティティ作成ページ</h3><p>最初にエンティティ作成を行うためのデータ入力ページを表示します。</p><p>以下のようにリソース名の後ろに「_create_」をつけてアクセスします。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/_create_
</pre><p>次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。</p><p>まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">
<input type="text" name="id" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">
<input type="text" name="name" value=""/>
</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">
<input type="text" name="price" value=""/>
</td>
</tr>
</tbody>
</table>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Input"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
</form>
</body>
</html>
</pre><p>このページでは以下のボタンが表示されています。</p><dl><dt>Input</dt><dd>データ登録</dd><dt>Cancel</dt><dd>キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。</dd></dl><p>Cancelボタンを押下するとトップページに戻ります。</p></section><section><h3>登録データ確認ページ</h3><p>データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。</p><pre class="java" name="code"><html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
<td>
<input type="submit" name="$submit" value="Back"/>
</td>
<td>
<input type="submit" name="$submit" value="Cancel"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
</form>
</body>
</html>
</pre><p>画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。</p><dl><dt>OK</dt><dd>確認OK</dd><dt>Back</dt><dd>入力画面にモデル</dd><dt>Cancel</dt><dd>キャンセル</dd></dl><p>Okボタンを押下するとエンティティ作成のための次の画面に遷移します。</p></section><section><h3>結果ページ</h3><p>登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<form action="" method="POST">
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">5</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Banana</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">250</td>
</tr>
</tbody>
</table>
<input type="hidden" name="id" value="5"/>
<input type="hidden" name="name" value="Banana"/>
<input type="hidden" name="price" value="250"/>
<table>
<tr>
<td>
<input type="submit" name="$submit" value="Ok"/>
</td>
</tr>
</table>
<input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;create-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
</form>
</body>
</html>
</pre><p>作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>HelloResource</title>
</head>
<body>
<ul>
<li>
<a href="product">List</a>
</li>
<li>
<a href="product/_create_">Create</a>
</li>
</ul>
</body>
</html>
</pre></section><section><h3>確認</h3><p>確認のためにリソースproductの一覧を表示してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>以下のように無事リソースが追加されました。</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/4.html">
<td class="">4</td>
<td class="">Banana</td>
<td class="">250</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。</p><p>今回はリソースの作成について説明しました。</p><p>今回はビューを登録していないので、エンティティ作成の入力画面、出力画面はデフォルトの画面となっています。次回はビューを登録することでアプリケーションで用意した入力画面、出力画面を使用する方法について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.12</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-13478901303499801192023-02-28T18:00:00.001+09:002023-02-28T18:00:00.157+09:00Cozy Web/エンティティ表示<div><p>前々回に作成したHelloResourceでは、Cozy Webでモデル定義をすることでWeb上のリソースとしてアクセスすることができることを説明しました。</p><p>前回はデモモードを使って、デモ時のみメモリDBにデータ投入する方法を紹介しました。</p><p>今回はHelloResourceを使って、モデルで定義したリソースをデザイン化した画面で表示する方法を説明します。</p><section><h2>HelloResource</h2><p>前々回作成したHelloResourceにエンティティの情報を表示するビューを追加します。</p><p>HelloResourceではビューは定義されていないので、エンティティのデフォルトの表示画面で表示されます。これをデザイン化した表示画面にすることが目的です。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。ここにビューを追加していきます。</p></section><section><h3>モデル</h3><p>WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを定義しています。</p><p>これがWebのリソースproductとなります。</p></section><section><h3>ビュー</h3><p>リソースproductの表示ビューとして以下のHTMLをプロジェクトルートにproduct.htmlとして配置します。</p><pre class="java" name="code"><html>
<head>
<title>Product List</title>
</head>
<body>
<c:table />
</body>
</html>
</pre><p>タグ c:table の場所にエンティティ一覧のモデルの内容が表示されます。それ以外の部分は通常のHTMLとして装飾できます。</p><p>また c:table の表示に関してもカスタマイズができますが、詳細は今後取り上げていく予定です。</p><p>product.htmlの代わりにproduct.jadeとして以下のJadeファイルを配置しても同じ振る舞いになります。</p><pre class="java" name="code">html
head
title Product List
body
c:table
</pre></section></section><section><h2>実行</h2><p>それではHelloResourceを実行してみましょう。</p><p>モデルとして定義したリソースのproductの一覧取得は以下になります。</p><p>WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<title>Product List</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>今回データとして投入した4つのエンティティに対応する情報が表示されています。</p></section><section><h2>詳細表示</h2><p>次はエンティティの詳細表示ビューです。</p><section><h3>ビュー</h3><p>リソースproductの詳細表示を行うビューとして以下のHTMLを用意します。</p><pre class="java" name="code"><html>
<head>
<title>Product Detail</title>
</head>
<body>
<c:detail />
</body>
</html>
</pre><p>タグ c:detail がエンティティの詳細表示を行うタグです。この場所にエンティティの詳細情報が表示されます。それ以外の部分は通常のHTMLとして装飾できます。</p><p>また c:detail の表示に関してもカスタマイズができますが、詳細は今後取り上げていく予定です。</p><p>このHTMLファイルをプロジェクトルート配下のproduct.entityディレクトリ配下に配置します。</p><p>product.entityディレクトリはリソースproductに対してエンティティ操作のシナリオに対するビューを格納するためのディレクトリです。サフィックスのentityが「エンティティ操作のシナリオに対するビュー」を示しています。</p><p>この配置を行うことにより「product/3」といったリソースproductのID 3のエンティティに対する表示のためのビューとして利用されます。</p></section><section><h3>実行</h3><p>それではHelloResourceを実行してみましょう。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/4
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>Product Detail</title>
</head>
<body>
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">4</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Berry</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">450</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>今回はモデルとして定義されたエンティティをリソースとして操作する際に、参照ビューを定義する方法について説明しました。</p><p>次回はエンティティ・リソースの更新についてみていきます。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.12</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-86872556794323343742023-01-31T18:00:00.003+09:002023-01-31T18:00:00.184+09:00Cozy Web/動作モード<div><p>Cozy Webでは開発中や製品版といった動作モードでアプリケーションの振る舞いを調整することができます。</p><p>今回は動作モードを使用して、開発時の初期データやデモ時に使用するデータの初期投入を行う方法について説明します。</p><section><h2>モード</h2><p>Cozy Webでは以下の動作モードがあります。</p><p>developモードで開発を行い、製品リリース時にproductionモードにします。</p><dl><dt>develop</dt><dd>開発モード(デフォルト)</dd><dt>production</dt><dd>製品モード</dd><dt>test</dt><dd>テスト・モード</dd><dt>demo</dt><dd>デモ・モード</dd></dl><p>test用途、デモ用途にはそれぞれtestモード、demoモードを使用します。</p></section><section><h2>HelloResource</h2><p>前回作成したHelloResourceに対して、デモ実行時に埋め込みDB上に初期化データを投入する設定を行います。</p><section><h3>準備</h3><p>前回の作業でcozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceができています。このHelloResourceを使用します。</p></section><section><h3>ビュー</h3><p>HelloResourceでは、Web画面を記述するビュー(*.html, *.jadeなど)は定義していません。リソースの表示はデフォルトのビュー機能によって自動的にレイアウトされます。</p><p>これは前回と変わりません。</p></section><section><h3>モデル</h3><p>WEB-INF/modelsでアプリケーションで使用するモデルを定義します。以下のモデル定義をmodel.orgとしてWEB-INF/modelsに格納します。</p><p>これも前回と変わりません。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre></section><section><h3>初期化データ</h3><p>WEB-INF配下に動作モード名のディレクトリを作成し、そこに各種定義ファイルを配置することで動作モード固有の定義を行うことができます。</p><p>今回はデモ時にデータの初期投入を行ってみます。</p><p>デモ・モードを示すdemoディレクトリをWEB-INF配下に作成し、そこにモデル定義のファイルmodels/model.orgを配置します。</p><p>WEB-INF/demo/models/model.orgの内容は以下になります。</p><pre class="java" name="code">* data-store
** product
*** data
1,Apple,300
2,Orange,350
3,Peach,400
4,berry,450
</pre><p>DBのprodutテーブルに4レコードを作成します。</p></section></section><section><h2>実行</h2><p>それではHelloResourceを実行してみましょう。</p><section><h3>一覧</h3><p>まず一覧取得です。</p><p>モデルとして定義したリソースのproductの一覧取得は以下になります。</p><p>WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
<tr data-href="product/3.html">
<td class="">4</td>
<td class="">Berry</td>
<td class="">450</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>今回データとして投入した4つのエンティティに対応する情報が表示されています。</p></section><section><h3>詳細</h3><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/4
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">4</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Berry</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">450</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>データベースを使用するシステム開発を行う場合、開発を進める実行環境上でのDBの構築が煩雑な作業となっています。今回はCozy Webのデータ移入機能とモードを組み合わせて対処する方法を紹介しました。</p><p>次回はビューを定義して、デザイン化された画面でエンティティ情報の表示を行ってみる予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.11</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-50586179349394328892022-12-31T18:00:00.001+09:002022-12-31T18:00:00.154+09:00Cozy Web/HelloResource<div><p>Cozy Webの目的の一つはモデル駆動開発とWeb開発を接続することにあります。</p><p>モデリングによって定義したモデルが、そのままWebアプリケーションのアプリケーション・ロジックとして動作し、Web画面をデザインするだけでWebアプリケーションが作成できるのが理想形です。</p><p>現時点ではその理想形にはまだまだ距離がありますが、部分的には実現できているところもあります。今回はエンティティをWebのリソースとしてアクセスする処理をモデルベースで実現する方法について説明します。</p><section><h2>HelloResource</h2><p>モデル駆動開発を指向した、モデルを使用したWebアプリケーションとしてHelloResourceを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceを作成します。</p></section><section><h3>ビュー</h3><p>HelloResourceでは、Web画面を記述するビュー(*.html, *.jadeなど)は定義していません。リソースの表示はデフォルトのビュー機能によって自動的にレイアウトされます。</p></section><section><h3>モデル</h3><p>WEB-INF/modelsでアプリケーションで使用するモデルを定義します。以下のモデル定義をmodel.orgとしてWEB-INF/modelsに格納します。</p><pre class="java" name="code">* entity
** product
*** features
table=product
*** attributes
| Name | Type | Multiplicity |
|-------+--------+--------------|
| id | token | 1 |
| name | string | 1 |
| price | int | 1 |
</pre><p>エンティティproductを以下の通りに定義しています。</p><ul><li>feature項で格納するテーブル名をproductと定義</li><li>属性としてid, name, priceの3つを定義</li></ul><p>モデルはCozy Webのスクリプト言語であるCozy Scriptの基盤となっているKaleidoxの提供するモデル駆動機能をベースとしています。</p><p>Kaleidoxの提供するモデル駆動機能は以下で説明しています。</p><ul><li><a href="https://modegramming.blogspot.com/2020/03/kaleidox.html">Kaleidox: モデル駆動開発</a></li><li><a href="https://modegramming.blogspot.com/2021/09/kaleidox.html">Kaleidox状態機械/エンティティ</a></li><li><a href="https://modegramming.blogspot.com/2021/10/kaleidox.html">Kaleidox状態機械/エンティティ・ストア</a></li><li><a href="https://modegramming.blogspot.com/2021/11/kaleidox.html">Kaleidox状態機械/エンティティの状態遷移</a></li><li><a href="https://modegramming.blogspot.com/2021/12/kaleidox.html">Kaleidox状態機械/エンティティの状態遷移によるアクション</a></li></ul><p>モデルの定義、データベースとの接続、状態機械の定義、状態機械によるイベント駆動といった機能を提供しています。</p><p>これらの機能をCozyではWebアプリケーションから使用することができるようになります。</p></section></section><section><h2>実行</h2><p>それではHelloResourceを実行してみましょう。</p><section><h3>一覧</h3><p>まず一覧取得です。</p><p>モデルとして定義したリソースのproductの一覧取得は以下になります。</p><p>WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
<title>product</title>
</head>
<body>
<table class="">
<caption class="">product</caption>
<thead class="">
<tr class="">
<th scope="col" class="">Id</th>
<th scope="col" class="">Name</th>
<th scope="col" class="">Price</th>
</tr>
</thead>
<tbody class="">
<tr data-href="product/1.html">
<td class="">1</td>
<td class="">Apple</td>
<td class="">300</td>
</tr>
<tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
<tr data-href="product/3.html">
<td class="">3</td>
<td class="">Peach</td>
<td class="">400</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>tableタグで3つのエンティティに対応する情報が表示されています。</p></section><section><h3>詳細</h3><pre class="java" name="code">$ curl http://localhost:8080/web/HelloResource/product/2
</pre><p>この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)</p><pre class="java" name="code"><?xml version="1.0"?>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="keywords" content="TBD"/>
<meta name="description" content="TBD"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="author" content="TBD"/>
</head>
<body>
<table class="">
<tbody>
<tr class="">
<th scope="row" class="">Id</th>
<td class="">2</td>
</tr>
<tr class="">
<th scope="row" class="">Name</th>
<td class="">Orange</td>
</tr>
<tr class="">
<th scope="row" class="">Price</th>
<td class="">350</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>一覧表示のidが2の部分は以下になります。</p><pre class="java" name="code"> <tr data-href="product/2.html">
<td class="">2</td>
<td class="">Orange</td>
<td class="">350</td>
</tr>
</pre><p>このエンティティが詳細情報として表示されているのが分かります。</p></section></section><section><h2>まとめ</h2><p>HelloResourceでは、必要最小限の構成要素としてモデル定義のみを作成しました。HTMLなどのビューは作成していません。</p><p>モデル定義を記述したmodel.orgを作成し、WEB-INF/modelsに配置するのみで、エンティティの内容が一覧画面、詳細画面として表示できることが分かりました。ビューの定義がない場合は、Cozy Webのデフォルト画面を使ってエンティティ情報が表示されました。</p><p>次回はビューを定義して、デザイン化された画面でエンティティ情報の表示を行ってみる予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.10</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-80792107896534042402022-11-30T18:00:00.001+09:002022-11-30T18:00:00.161+09:00Cozy Web/HelloScript<div><p>前回はCozy Scriptの組込み関数を使用して、システムが提供するオペレーションをフォーム画面から呼出して使用する方法について説明しました。</p><p>今回はフォーム画面から入力したパラメタを引数にしてCozy Scriptを実行する方法について説明します。</p><section><h2>HelloScript</h2><p>フォームから使用できるアプリケーション・ロジックをCozy Scriptのスクリプトとして記述することができます。</p><p>Cozy scriptを用いたWebアプリケーションHelloScriptを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloScriptを作成します。</p></section><section><h3>Formページ</h3><p>フォームを使った入力画面として以下のページをindex.jadeとしてホームディレクトリに配置します。</p><pre class="java" name="code">-@val form: ViewForm
html
head
title HelloScript
body
form(method="POST" action={form.action})
input(hidden="true" name="$scenario" value={form.scenario})
input(name="arg1" value={form.arg1})
input(name="arg2" value={form.arg2})
input(name="arg3" value={form.arg3})
button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><section><h4>ViewFormオブジェクト</h4><p>以下の宣言でフォームの設定に必要なViewFormを参照可能にします。</p><pre class="java" name="code">-@val form: ViewForm
</pre></section><section><h4>Form/action</h4><p>actionにViewFormオブジェクトのaction属性を設定します。</p><pre class="java" name="code"> form(method="POST" action={form.action})
</pre><p>今回の場合は空文字が設定されます。入力と同じページにフォームのPOSTが行われるということですね。</p><p>POST処理に必要な情報は後述する「$scenario」に設定されています。</p></section><section><h4>Input/Hidden</h4><p>Hidden属性のInputで入力する「$scenario」プロパティにViewFormオブジェクトのscenario属性を設定します。</p><pre class="java" name="code"> input(hidden="true" name="$scenario" value={form.scenario})
</pre><p>今回の場合は「{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}」が設定されています。URLエンコーディングを解除した値は「{"name":"invoke-operation","state":"input","data":{}}」です。</p><p>Cozy Webがフォーム処理を行うために必要な情報が設定されています。</p></section><section><h4>Inputデータ</h4><p>Hidden属性のないInputでデータ入力を行います。</p><p>今回は以下の3行が対象です。</p><pre class="java" name="code"> input(name="arg1" value={form.arg1})
input(name="arg2" value={form.arg2})
input(name="arg3" value={form.arg3})
</pre><p>nameにarg1,arg2,arg3を指定しているので、arg1プロパティとarg2プロパティ, arg3プロパティの3つのプロパティの入力ということになります。値のデフォルト値としてViewFormオブジェクトのarg1属性とarg2属性の値を設定しています。今回のケースでは空文字が設定されます。</p></section><section><h4>Input/Ok</h4><p>OK用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
</pre><p>name属性に「$submit」、value属性に「ok」を指定しています。</p></section><section><h4>Input/Cancel</h4><p>キャンセル用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><p>name属性に「$submit」、value属性に「cancel」を指定しています。</p></section></section><section><h3>コントローラ</h3><p>WEB-INF/controllersにindex.jade用のコントローラである以下のindex.jsonを配置します。</p><pre class="java" name="code">{
"action": "script-scenario",
"script0": "(+ 1 2 3)",
"script": "(+ arg1 (* arg2 arg3))",
"method": "POST",
"successView": "index_complete",
"errorView": "index_error",
"parameters": [{
"name": "arg1",
"datatype": "int"
},{
"name": "arg2",
"datatype": "int"
},{
"name": "arg3",
"datatype": "int"
}]
}
</pre><section><h4>action</h4><p>コントローラのアクションとしてscript-scenarioを指定しています。</p><pre class="java" name="code"> "action": "script-scenario",
</pre><p>script-scenarioは、フォームで入力したパラメタ入力を使ってスクリプトを呼び出し、その結果をビューに渡すモデルとして生成する処理を行うシナリオです。</p><p>フォーム入力にまつわるWebブラウザとサーバ間のインタラクションをシナリオに従って実現します。</p></section><section><h4>script</h4><p>実行するスクリプトをCozy Scriptで記述します。</p><pre class="java" name="code"> "script": "(+ arg1 (* arg2 arg3))",
</pre></section><section><h4>method</h4><p>メソッドはPOSTを指定しています。</p><pre class="java" name="code"> "method": "POST",
</pre><p>FormのメソッドがPOSTのものを受け付けます。</p></section><section><h4>successView</h4><p>successViewにはindex_completeを指定しています。</p><pre class="java" name="code"> "successView": "index_complete",
</pre><p>コントローラの処理が成功するとこのページに遷移します。</p></section><section><h4>errorView</h4><p>errorViewにはindex_errorを指定しています。</p><pre class="java" name="code"> "errorView": "index_error",
</pre><p>コントローラの処理が失敗するとこのページに遷移します。</p></section><section><h4>parameters</h4><p>フォームから入力されるパラメタとして、パラメタ名とデータ型を指定しています。</p><pre class="java" name="code"> "parameters": [{
"name": "arg1",
"datatype": "int"
},{
"name": "arg2",
"datatype": "int"
},{
"name": "arg3",
"datatype": "int"
}]
</pre><p>パラメタは、パラメタ名arg1でデータ型int, パラメタ名arg2でデータ型int, パラメタ名arg3でデータ型intの3つです。</p></section></section><section><h3>成功ページ</h3><p>成功ページとして以下のindex_complete.htmlを用意します。コントローラのsuccessViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Script Success</title>
</head>
<body>
<h1>Script Success</h1>
<c:model/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行結果のモデルの内容を表形式で表示するものです。</p><pre class="java" name="code"> <c:model/>
</pre><p>今回の場合は、スクリプトの実行結果が出力されます。</p></section><section><h3>エラーページ</h3><p>成功ページとして以下のindex_error.htmlを用意します。コントローラのerrorViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Script Error</title>
</head>
<body>
<h1>Script Error</h1>
<c:error/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行時にエラーが発生した場合、そのエラーを表形式で表示するものです。</p><pre class="java" name="code"> <c:error/>
</pre><p>今回の場合は、スクリプトの実行結果がエラーとなる場合に出力されます。</p></section></section><section><h2>実行</h2><section><h3>Formページ</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloScript を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloScript/
</pre><p>以下のHTML文書が返されます。</p><pre class="java" name="code"><!DOCTYPE html>
<html>
<head>
<title>HelloScript</title>
</head>
<body>
<form action="" method="POST">
<input value="{&quot;name&quot;:&quot;execute-script&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}" name="$scenario" hidden="true" />
<input value="" name="arg1" />
<input value="" name="arg2" />
<input value="" name="arg3" />
<button value="ok" name="$submit" id="submitbutton" type="submit">Submit</button>
<button value="cancel" name="$submit" id="cancelbutton" type="submit">Cancel</button>
</form>
</body>
</html>
</pre></section><section><h3>OK</h3><p>OKボタンの押下は以下のcurlに相当します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloScript/ -X POST \
--data-urlencode '$submit=ok' \
--data-urlencode 'arg1=3' \
--data-urlencode 'arg2=8' \
--data-urlencode 'arg3=5' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><p>OKボタン押下と同等の上記curlの結果、以下のHTMLが出力されました。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Script Success</title>
</head><body>
<h1>Script Success</h1>
43
</body></html>
</pre><p>c:modelタグの場所に、スクリプト「(+ 3 (* 8 5))」の計算結果である43が出力されています。</p></section></section><section><h2>まとめ</h2><p>今回はフォーム画面から入力したパラメタを引数にしてCozy Scriptを実行する方法について説明しました。</p><p>次回はCozy Scriptに組み込まれたモデル駆動の機能を使用してリソースに対するアクセスを実現する方法について説明する予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.9</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-15548137891658695752022-10-31T18:00:00.001+09:002022-10-31T18:00:00.178+09:00Cozy Web/HelloOperation<div><p>フォーム処理ではサーバーサイドでアプリケーション・ロジックを実行する必要があります。</p><p>Cozyではアプリケーション・ロジックを記述する方式としてKaleidoxの関数を使用することが可能です。</p><p>今回はKaleidoxの組込み関数「+」をCozy Webから使用する方法について見ていきます。</p><section><h2>HelloOperation</h2><p>フォームから使用できるアプリケーション・ロジックはオペレーションとして提供されています。</p><p>Kaleidoxの組込み関数はオペレーションとして登録されているので、そのまま使用することができます。</p><p>フォームを用いたWebアプリケーションHelloOperationを作成します。</p><p>HelloOperationでは、Kaleidoxの「+」関数をCozyのオペレーションとして実行することでフォームで入力した数値の加算を行います。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloOperationを作成します。</p></section><section><h3>Formページ</h3><p>フォームを使った入力画面として以下のページをindex.jadeとしてホームディレクトリに配置します。</p><pre class="java" name="code">-@val form: ViewForm
html
head
title HelloForm
body
form(method="POST" action={form.action})
input(hidden="true" name="$scenario" value={form.scenario})
input(name="arg1" value={form.arg1})
input(name="arg2" value={form.arg2})
button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><section><h4>ViewFormオブジェクト</h4><p>以下の宣言でフォームの設定に必要なViewFormを参照可能にします。</p><pre class="java" name="code">-@val form: ViewForm
</pre></section><section><h4>Form/action</h4><p>actionにViewFormオブジェクトのaction属性を設定します。</p><pre class="java" name="code"> form(method="POST" action={form.action})
</pre><p>今回の場合は空文字が設定されます。入力と同じページにフォームのPOSTが行われるということですね。</p><p>POST処理に必要な情報は後述する「$scenario」に設定されています。</p></section><section><h4>Input/Hidden</h4><p>Hidden属性のInputで入力する「$scenario」プロパティにViewFormオブジェクトのscenario属性を設定します。</p><pre class="java" name="code"> input(hidden="true" name="$scenario" value={form.scenario})
</pre><p>今回の場合は「{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}」が設定されています。URLエンコーディングを解除した値は「{"name":"invoke-operation","state":"input","data":{}}」です。</p><p>Cozy Webがフォーム処理を行うために必要な情報が設定されています。</p></section><section><h4>Inputデータ</h4><p>Hidden属性のないInputでデータ入力を行います。</p><p>今回は以下の2行が対象です。</p><pre class="java" name="code"> input(name="arg1" value={form.arg1})
input(name="arg2" value={form.arg2})
</pre><p>nameにarg1とarg2を指定しているので、arg1プロパティとarg2プロパティの2つのプロパティの入力ということになります。値のデフォルト値としてViewFormオブジェクトのarg1属性とarg2属性の値を設定しています。今回のケースでは空文字が設定されます。</p></section><section><h4>Input/Ok</h4><p>OK用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
</pre><p>name属性に「$submit」、value属性に「ok」を指定しています。</p></section><section><h4>Input/Cancel</h4><p>キャンセル用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><p>name属性に「$submit」、value属性に「cancel」を指定しています。</p></section></section><section><h3>コントローラ</h3><p>WEB-INF/controllersにindex.jade用のコントローラである以下のindex.jsonを配置します。</p><pre class="java" name="code">{
"action": "invoke-operation-scenario",
"operation": "+",
"method": "POST",
"successView": "index_complete",
"errorView": "index_error",
"parameters": [{
"arg1": "int",
"arg2": "int"
}]
}
</pre><section><h4>action</h4><p>コントローラのアクションとしてinvoke-operation-scenarioを指定しています。</p><pre class="java" name="code"> "action": "invoke-operation-scenario",
</pre><p>invoke-operation-scenarioは、フォームでパラメタ入力し、このパラメタを使ってオペレーションを呼び出し、その結果をビューに渡すモデルとして生成する処理を行うシナリオです。</p><p>フォーム入力にまつわるWebブラウザとサーバ間のインタラクションをシナリオに従って実現します。</p></section><section><h4>operation</h4><p>実行するオペレーションとして+を指定しています。</p><pre class="java" name="code"> "operation": "+",
</pre><p>+オペレーションはKaleidoxが定義している関数で、数値の加算をおこないます。</p><p>CozyではKaleidoxの関数をinvoke-operation-scenarioで呼び出すことができるオペレーションとして使用できるようになっています。</p></section><section><h4>method</h4><p>メソッドはPOSTを指定しています。</p><pre class="java" name="code"> "method": "POST",
</pre><p>FormのメソッドがPOSTのものを受け付けます。</p></section><section><h4>successView</h4><p>successViewにはindex_completeを指定しています。</p><pre class="java" name="code"> "successView": "index_complete",
</pre><p>コントローラの処理が成功するとこのページに遷移します。</p></section><section><h4>errorView</h4><p>errorViewにはindex_errorを指定しています。</p><pre class="java" name="code"> "errorView": "index_error",
</pre><p>コントローラの処理が失敗するとこのページに遷移します。</p></section><section><h4>parameters</h4><p>フォームから入力されるパラメタとして、パラメタ名とデータ型を指定しています。</p><pre class="java" name="code"> "parameters": [{
"arg1": "int",
"arg2": "int"
}]
</pre><p>パラメタは、パラメタ名arg1でデータ型intとパラメタ名arg2でデータ型intの2つです。</p></section></section><section><h3>成功ページ</h3><p>成功ページとして以下のindex_complete.htmlを用意します。コントローラのsuccessViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Operation Success</title>
</head>
<body>
<h1>Operation Success</h1>
<c:model/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行結果のモデルの内容を表形式で表示するものです。</p><pre class="java" name="code"> <c:model/>
</pre><p>今回の場合は、+オペレーションの結果が出力されます。</p></section><section><h3>エラーページ</h3><p>成功ページとして以下のindex_error.htmlを用意します。コントローラのerrorViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Operation Error</title>
</head>
<body>
<h1>Operation Error</h1>
<c:error/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行時にエラーが発生した場合、そのエラーを表形式で表示するものです。</p><pre class="java" name="code"> <c:error/>
</pre><p>今回の場合は、loopbackオペレーションがエラーとなる場合に出力されます。</p></section></section><section><h2>実行</h2><section><h3>Formページ</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloOperation を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloOperation/
</pre><p>以下のHTML文書が返されます。</p><pre class="java" name="code"><!DOCTYPE html>
<html>
<head>
<title>HelloForm</title>
</head>
<body>
<form action="" method="POST">
<input value="{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}" name="$scenario" hidden="true" />
<input value="" name="arg1" />
<input value="" name="arg2" />
<button value="ok" name="$submit" id="submitbutton" type="submit">Submit</button>
<button value="cancel" name="$submit" id="cancelbutton" type="submit">Cancel</button>
</form>
</body>
</html>
</pre></section><section><h3>OK</h3><p>OKボタンの押下は以下のcurlに相当します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloOperation/ -X POST \
--data-urlencode '$submit=ok' \
--data-urlencode 'arg1=3' \
--data-urlencode 'arg2=8' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><p>OKボタン押下と同等の上記curlの結果、以下のHTMLが出力されました。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Operation Success</title>
</head><body>
<h1>Operation Success</h1>
11
</body></html>
</pre><p>c:modelタグの場所に、「+ 3 8」の計算結果である11が出力されています。</p></section></section><section><h2>まとめ</h2><p>今回はCozy WebでHTMLフォームの処理にKaleidoxの組込み関数を使用する方法について説明しました。</p><p>Cozy WebではHTMLフォームを使った処理はコントローラに宣言的な定義をするだけで、Webとサーバー間のインタラクションを伴う状態遷移の管理を行ってくれます。さらにオペレーションとして登録された各種処理も実行してくれるので、オペレーションを実装すれば後はWeb画面のデザインをするだけでHTMLフォーム処理を実現することができるわけです。</p><p>今回はKaleidoxの組込み関数を使用しましたが、次回はKaleidoxのスクリプト機能を使用してHTMLフォームによる処理を実現する方法を説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.8</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-46445591914381552292022-09-30T20:00:00.010+09:002022-09-30T20:00:00.162+09:00Cozy Web/HelloForm<div><p>Webアプリケーション開発では、フォーム処理の開発が一つのポイントになります。やりたいことそのものは単純でもHTTPプロトコルを使ってWebブラウザとサーバー間でやり取りをするシーケンスの中で実現するのは案外大変です。</p><p>Cozy Webではこの煩雑な処理を簡単に実現する機能を提供しています。</p><p>今回はCozy Webでのフォーム入力の処理方法について説明します。</p><section><h2>HelloForm</h2><p>フォームを用いたWebアプリケーションHelloFormを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloFormを作成します。</p></section><section><h3>Formページ</h3><p>フォームを使った入力画面として以下のページをindex.jadeとしてホームディレクトリに配置します。</p><pre class="java" name="code">-@val form: ViewForm
html
head
title HelloForm
body
form(method="POST" action={form.action})
input(hidden="true" name="$scenario" value={form.scenario})
input(name="name" value={form.name})
button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><section><h4>ViewFormオブジェクト</h4><p>以下の宣言でフォームの設定に必要なViewFormを参照可能にします。</p><pre class="java" name="code">-@val form: ViewForm
</pre></section><section><h4>Form/action</h4><p>actionにViewFormオブジェクトのaction属性を設定します。</p><pre class="java" name="code"> form(method="POST" action={form.action})
</pre><p>今回の場合は空文字が設定されます。入力と同じページにフォームのPOSTが行われるということですね。</p><p>POST処理に必要な情報は後述する「$scenario」に設定されています。</p></section><section><h4>Input/Hidden</h4><p>Hidden属性のInputで入力する「$scenario」プロパティにViewFormオブジェクトのscenario属性を設定します。</p><pre class="java" name="code"> input(hidden="true" name="$scenario" value={form.scenario})
</pre><p>今回の場合は「{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}」が設定されています。URLエンコーディングを解除した値は「{"name":"invoke-operation","state":"input","data":{}}」です。</p><p>Cozy Webがフォーム処理を行うために必要な情報が設定されています。</p></section><section><h4>Inputデータ</h4><p>Hidden属性のないInputでデータ入力を行います。</p><p>今回は以下の1行が対象です。</p><pre class="java" name="code"> input(name="name" value={form.name})
</pre><p>nameに「name」指定しているので、nameプロパティの入力ということになります。値のデフォルト値としてViewFormオブジェクトのname属性の値を設定しています。今回のケースでは空文字が設定されます。</p></section><section><h4>Input/Ok</h4><p>OK用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
</pre><p>name属性に「$submit」、value属性に「ok」を指定しています。</p></section><section><h4>Input/Cancel</h4><p>キャンセル用のサブミットボタンとして以下のButtonを設定しました。</p><pre class="java" name="code"> button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel
</pre><p>name属性に「$submit」、value属性に「cancel」を指定しています。</p></section></section><section><h3>SSPの場合</h3><p>フォームのような構造を記述するページの場合、今回の例ではJadeの方が簡潔に記述できるので本ページではJadeを使っていますが、JSP(JavaServer Page)のようなHTMLライクな文法を持つSSP(Scala Server Pages)を使って記述することも可能です。</p><p>SSPの場合は以下になります。</p><pre class="java" name="code"><%@ val form: ViewForm %>
<html>
<head>
<title>HelloForm</title>
</head>
<body>
<form method="POST" action="${form.action}">
<input hidden="true" name="$scenario" value="${form.scenario}"/>
<input name="name" value="${form.name}"/>
<button type="submit" id="submitbutton" name="$submit" value="ok">Submit</button>
<button type="submit" id="cancelbutton" name="$submit" value="cancel">Cancel</button>
</form>
</body>
</html>
</pre><p>フォーム記述に使用するViewFormオブジェクトを変数formに束縛する宣言は以下になります。</p><pre class="java" name="code"><%@ val form: ViewForm %>
</pre><p>Formタグに設定する情報はJade版と同じものです。</p></section><section><h3>コントローラ</h3><p>WEB-INF/controllersにindex.jade用のコントローラである以下のindex.jsonを配置します。</p><pre class="java" name="code">{
"action": "invoke-operation-scenario",
"operation": "loopback",
"method": "POST",
"successView": "index_complete",
"errorView": "index_error",
"parameters": [{
"name": "token"
}]
}
</pre><section><h4>action</h4><p>コントローラのアクションとしてinvoke-operation-scenarioを指定しています。</p><pre class="java" name="code"> "action": "invoke-operation-scenario",
</pre><p>invoke-operation-scenarioは、フォームでパラメタ入力し、このパラメタを使ってオペレーションを呼び出し、その結果をビューに渡すモデルとして生成する処理を行うシナリオです。</p><p>フォーム入力にまつわるWebブラウザとサーバ間のインタラクションをシナリオに従って実現します。</p></section><section><h4>operation</h4><p>実行するオペレーションとしてloopbackを指定しています。</p><pre class="java" name="code"> "operation": "loopback",
</pre><p>loopbackは入力したデータをそのまま表形式のモデルとして受け渡すオペレーションです。</p></section><section><h4>method</h4><p>メソッドはPOSTを指定しています。</p><pre class="java" name="code"> "method": "POST",
</pre><p>FormのメソッドがPOSTのものを受け付けます。</p></section><section><h4>successView</h4><p>successViewにはindex_completeを指定しています。</p><pre class="java" name="code"> "successView": "index_complete",
</pre><p>コントローラの処理が成功するとこのページに遷移します。</p></section><section><h4>errorView</h4><p>errorViewにはindex_errorを指定しています。</p><pre class="java" name="code"> "errorView": "index_error",
</pre><p>コントローラの処理が失敗するとこのページに遷移します。</p></section><section><h4>parameters</h4><p>フォームから入力されるパラメタとして、パラメタ名とデータ型を指定しています。</p><pre class="java" name="code"> "parameters": [{
"name": "token"
}]
</pre><p>パラメタは、パラメタ名nameでデータ型はトークン文字列の一つだけです。</p></section></section><section><h3>成功ページ</h3><p>成功ページとして以下のindex_complete.htmlを用意します。コントローラのsuccessViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Form Success</title>
</head>
<body>
<h1>Form Success</h1>
<c:model/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行結果のモデルの内容を表形式で表示するものです。</p><pre class="java" name="code"> <c:model/>
</pre><p>今回の場合は、loopbackオペレーションの結果が出力されます。</p></section><section><h3>エラーページ</h3><p>成功ページとして以下のindex_error.htmlを用意します。コントローラのerrorViewで指定したページです。</p><pre class="java" name="code"><html>
<head>
<title>Form Error</title>
</head>
<body>
<h1>Form Error</h1>
<c:error/>
</body>
</html>
</pre><p>このページ内の以下のタグはコントローラの実行時にエラーが発生した場合、そのエラーを表形式で表示するものです。</p><pre class="java" name="code"> <c:error/>
</pre><p>今回の場合は、loopbackオペレーションがエラーとなる場合に出力されます。</p></section></section><section><h2>実行</h2><section><h3>Formページ</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloForm を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloForm/
</pre><p>以下のHTML文書が返されます。</p><pre class="java" name="code"><!DOCTYPE html>
<html>
<head>
<title>HelloForm</title>
</head>
<body>
<form action="" method="POST">
<input value="{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}" name="$scenario" hidden="true" />
<input value="" name="name" />
<button value="ok" name="$submit" id="submitbutton" type="submit">Submit</button>
<button value="cancel" name="$submit" id="cancelbutton" type="submit">Cancel</button>
</form>
</body>
</html>
</pre><p>Web画面は以下のとおりです。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcBa6EQih-TzDfAlBjiSUnU6OUVq6vfFn-dBSVLTY_vaW8moZmDt-eEW9lrfHeL5kXdLLLCtcnEj39242XvshkGagJ-d50U3wfqij5YO9anJt9Q8Hv8CbV1HuJUCv-w42Gc4p5KPBf-jkPnckyH0zxFdBEqAgJjuP5f2dGQtjWtxP-HFMhd-z4_irw/s2290/Form.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="2178" data-original-width="2290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcBa6EQih-TzDfAlBjiSUnU6OUVq6vfFn-dBSVLTY_vaW8moZmDt-eEW9lrfHeL5kXdLLLCtcnEj39242XvshkGagJ-d50U3wfqij5YO9anJt9Q8Hv8CbV1HuJUCv-w42Gc4p5KPBf-jkPnckyH0zxFdBEqAgJjuP5f2dGQtjWtxP-HFMhd-z4_irw/s320/Form.jpg"/></a></div>
</section><section><h3>OK</h3><pre class="java" name="code">$ curl http://localhost:8080/web/HelloForm/ -X POST \
--data-urlencode '$submit=ok' \
--data-urlencode 'name=abc' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Form Success</title>
</head><body>
<h1>Form Success</h1>
<table class="">
<tbody><tr class=""><th scope="row" class="">$submit</th><td class="">ok</td></tr><tr class=""><th scope="row" class="">Name</th><td class="">abc</td></tr><tr class=""><th scope="row" class="">$scenario</th><td class="">{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}</td></tr></tbody>
</table>
</body></html>
</pre><p>Web画面は以下のとおりです。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizN46hOiYywIj58XmBhfGrUK9docyavKpJxuvW98gC7a2_qiKlTGZMKOwWCVv0uxUxZ9hpD563fn-3wS_9YqtAmiEMu39faYi2hE1UuLE-3XNACghyy-RWgX_rYu7J8IqLGRPIZXf3WAdlvMpskkH6wEpQGJwrQiiD0vJxZVM-vtFhDbw9N1bw0Htg/s2290/Success.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="2178" data-original-width="2290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizN46hOiYywIj58XmBhfGrUK9docyavKpJxuvW98gC7a2_qiKlTGZMKOwWCVv0uxUxZ9hpD563fn-3wS_9YqtAmiEMu39faYi2hE1UuLE-3XNACghyy-RWgX_rYu7J8IqLGRPIZXf3WAdlvMpskkH6wEpQGJwrQiiD0vJxZVM-vtFhDbw9N1bw0Htg/s320/Success.jpg"/></a></div>
</section><section><h3>エラー</h3><p>コントローラで指定したloopbackオペレーションでは、データのいずれかに「#500」のような「#」記号の後ろに数値を入れた文字列を入力すると、この数値をエラー番号としたエラーが発生するようになっています。</p><p>この機能を利用してエラーページの動作を確認してみましょう。</p><p>Webページの入力から「#500」を入れてSubmitボタンを押したときのHTTPの送信は以下のcurlで実現できます。</p><p>「name=#500」となっているところがキモです。</p><pre class="java" name="code">$ curl -v http://localhost:8080/web/HelloForm/ -X POST \
--data-urlencode '$submit=ok' \
--data-urlencode 'name=#500' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><p>この結果以下のHTMLが返ってきました。</p><pre class="java" name="code"><!DOCTYPE html>
<html><head>
<title>Form Error</title>
</head><body>
<h1>Form Error</h1>
<table class="">
<tbody><tr class=""><th scope="row" class="">Code</th><td class="">500</td></tr><tr class=""><th scope="row" class="">Message</th><td class="" /></tr><tr class=""><th scope="row" class="">Top URI</th><td class="" /></tr><tr class=""><th scope="row" class="">Back URI</th><td class="" /></tr><tr class=""><th scope="row" class="">Exception Message</th><td class="" /></tr><tr class=""><th scope="row" class="">Exception Stack</th><td class="" /></tr><tr class=""><th scope="row" class="">Call Tree</th><td class="" /></tr></tbody>
</table>
</body></html>
</pre><p>Web画面は以下のとおりです。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIvYv_jXRvRBDvtFxQgUL_7alMVfDvzmgm-31LveDqwsZusxnlGaetRJc_Ne3s5Uoo1vyahqr7quakP7YM72k-0sq0ryO8AnKbBxbf8MwaohQ15ASBjoiuxLcyD4CSc_kRnClq0GESDpGcNuMSZWEyqibtp5BJ1tfBoyUwBRv7e6puesNI0PaBmj4r/s2290/Error.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="2178" data-original-width="2290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIvYv_jXRvRBDvtFxQgUL_7alMVfDvzmgm-31LveDqwsZusxnlGaetRJc_Ne3s5Uoo1vyahqr7quakP7YM72k-0sq0ryO8AnKbBxbf8MwaohQ15ASBjoiuxLcyD4CSc_kRnClq0GESDpGcNuMSZWEyqibtp5BJ1tfBoyUwBRv7e6puesNI0PaBmj4r/s320/Error.jpg"/></a></div>
</section><section><h3>キャンセル</h3><p>invoke-operattionシナリオでは、cancelがサブミットされるとキャンセル動作が行われます。</p><pre class="java" name="code">$ curl -v http://localhost:8080/web/HelloForm/ -X POST \
--data-urlencode '$submit=cancel' \
--data-urlencode 'name=#500' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><p>キャンセル動作を行うと、元のページにリダイレクトされ、新規にデータ入力の状態になります。</p><pre class="java" name="code">* Connected to localhost (::1) port 8080 (#0)
> POST /web/HelloForm HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
> Content-Length: 128
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Date: Thu, 29 Sep 2022 01:29:31 GMT
< Content-Type: text/html;charset=utf-8
< Cache-Control: private,no-store,no-cache,must-revalidate
< Location: http://localhost:8080/web/HelloForm
< Content-Length: 0
< Server: Jetty(9.4.38.v20210224)
<
* Connection #0 to host localhost left intact
</pre><p>curlの-Lスイッチで、リダイレクトをフォローしてみます。</p><pre class="java" name="code">$ curl -L http://localhost:8080/web/HelloForm/ -X POST \
--data-urlencode '$submit=cancel' \
--data-urlencode 'name=#500' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'
</pre><p>そうすると以下のように、無事元のフォームページが返ってきました。</p><pre class="java" name="code"><!DOCTYPE html>
<html>
<head>
<title>HelloForm</title>
</head>
<body>
<form action="" method="POST">
<input value="{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}" name="$scenario" hidden="true" />
<input value="" name="name" />
<button value="ok" name="$submit" id="submitbutton" type="submit">Submit</button>
<button value="cancel" name="$submit" id="cancelbutton" type="submit">Cancel</button>
</form>
</body>
</html>
</pre><p>Web画面は以下のとおりです。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcBa6EQih-TzDfAlBjiSUnU6OUVq6vfFn-dBSVLTY_vaW8moZmDt-eEW9lrfHeL5kXdLLLCtcnEj39242XvshkGagJ-d50U3wfqij5YO9anJt9Q8Hv8CbV1HuJUCv-w42Gc4p5KPBf-jkPnckyH0zxFdBEqAgJjuP5f2dGQtjWtxP-HFMhd-z4_irw/s2290/Form.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="2178" data-original-width="2290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhcBa6EQih-TzDfAlBjiSUnU6OUVq6vfFn-dBSVLTY_vaW8moZmDt-eEW9lrfHeL5kXdLLLCtcnEj39242XvshkGagJ-d50U3wfqij5YO9anJt9Q8Hv8CbV1HuJUCv-w42Gc4p5KPBf-jkPnckyH0zxFdBEqAgJjuP5f2dGQtjWtxP-HFMhd-z4_irw/s320/Form.jpg"/></a></div>
</section></section><section><h2>まとめ</h2><p>今回はCozy WebでHTMLフォームを取り扱う方法について説明しました。</p><p>フォームを扱う場合、Webとサーバ間のインタラクションに伴う状態遷移の管理を行う処理を作るのがなかなか大変です。Cozy Webでは、コントローラに宣言的な定義をするだけで、この処理を簡単に行ってくれることが分かりました。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.7</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-47379322967357672992022-08-31T18:00:00.001+09:002022-08-31T18:00:00.293+09:00Cozy Web/Webライブラリ<div><p>前回「Cozy Web/レイアウト」ではBootstrapベースのレイアウトを持った共通テンプレートをWebアプリケーション全体で共通化して利用する方法について説明しました。</p><p>この共通テンプレートを、複数のWebアプリケーションで共有できると便利です。</p><p>このことを実現するため、Cozy Webでは複数のWebアプリケーションから共有できるWebライブラリを作成する機能を提供しています。</p><p>今回はこのWebライブラリについてみていきます。</p><section><h2>LibHello</h2><p>まず、Webライブラリとして使用するLibHelloプロジェクトを作成します。</p><p>プロジェクトの構成は、ここまで紹介してきた通常のWebアプリケーションと同じものになります。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、WebライブラリのホームとなるディレクトリLibHelloを作成します。このディレクトリLibHelloをWebライブラリのホームディレクトリとなります。</p></section><section><h3>共通テンプレート</h3><p>Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。これは「Cozy Web/レイアウト」で作成したものと同じものです。このテンプレートページでBootstrapに必要な設定を行っています。</p><pre class="java" name="code">-@val model: ViewModel
!!! 5
html(lang="ja")
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1")
link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous")
=model.pageTitle
body
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous")
header
=model.header
=model.navigation
div(class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto")
div(class="row flex-grow-sm-1 flex-grow-0")
aside(class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3")
div(class="bg-light border p-1 h-100 sticky-top")
=model.sidebar
main(class="col overflow-auto h-100")
=model.content
footer
=model.footer
</pre></section><section><h3>部品ページ</h3><p>Webページの部品はWEB-INF/partialsに格納します。いずれも「Cozy Web/レイアウト」で作成したものと同じものです。</p><section><h4>ヘッダー</h4><p>ヘッダーとして以下のheader.jadeをWEB-INF/partialsに格納しました。「Cozy Web/レイアウト」で作成したものと同じものです。Bootstrapのクラスを設定しています。</p><pre class="java" name="code">nav(class="navbar navbar-light bg-primary")
div(class="container-fluid")
span(class="navbar-brand mb-0 h1") Cozy Web
</pre></section><section><h4>ナビゲーション・バー</h4><p>ナビゲーション・バーとして以下のnavigation.jadeをWEB-INF/partialsに格納しました。「Cozy Web/レイアウト」で作成したものと同じものです。Bootstrapの機能を用いてナビゲーション・バーを実現しています。</p><pre class="java" name="code">nav(class="navbar navbar-expand-lg navbar-light bg-light")
div(class="container-fluid")
a(class="navbar-brand" href="#") Navbar
button(class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation")
span(class="navbar-toggler-icon")
div(class="collapse navbar-collapse" id="navbarNav")
ul(class="navbar-nav")
li(class="nav-item")
a(class="nav-link active" aria-current="page" href="#") Home
li(class="nav-item")
a(class="nav-link" href="#") Features
li(class="nav-item")
a(class="nav-link" href="#") Pricing
li(class="nav-item")
a(class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true") Disabled
</pre></section><section><h4>フッター</h4><p>フッターとして以下のfooter.jadeをWEB-INF/partialsに格納しました。「Cozy Web/レイアウト」で作成したものと同じものです。Bootstrapのクラスを設定しています。</p><pre class="java" name="code">nav(class="navbar navbar-light bg-secondary")
span Cozy Web
</pre></section><section><h4>サイド・バー</h4><p>サイド・バーとして以下のsidebar.jadeをWEB-INF/partialsに格納しました。「Cozy Web/レイアウト」で作成したものと同じものです。Bootstrapの機能を用いてサイド・バーを実現しています。</p><pre class="java" name="code">ul(class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate")
li(class="nav-item")
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-house fs-5")
span(class="d-none d-sm-inline") Home
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-speedometer fs-5")
span(class="d-none d-sm-inline") Dashboard
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-card-text fs-5")
span(class="d-none d-sm-inline") Orders
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-bricks fs-5")
span(class="d-none d-sm-inline") Products
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-people fs-5")
span(class="d-none d-sm-inline") Customers
</pre></section></section><section><h3>構成</h3><p>ここまでは、前回「Cozy Web/レイアウト」のLayoutBootstrapと一点を除いて同一の構成です。異なっているのは、index.htmlがないこと。Webライブラリなので必要ないためです。</p></section></section><section><h2>HellLib</h2><p>WebライブラリLibHelloを作成したので、このWebライブラリを使ったWebアプリケーションHelloLibを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、WebライブラリのホームとなるディレクトリHelloLibを作成します。このディレクトリHelloLibをWebライブラリのホームディレクトリとなります。</p></section><section><h3>project.conf</h3><p>使用するWebライブラリの定義はwepapp.confで行います。</p><pre class="java" name="code">extend: LibHello
</pre><p>extendプロパティによって、親となるWebライブラリであるLibHelloを指定しています。この設定を行うことでWebライブラリの持っている機能をすべて引き継ぐことができます。</p><p>このwebapp.confをWEB-INFに格納します。</p><p>これで設定は完了です。</p></section><section><h3>Webページ</h3><p>共通ページデザインは、LibHelloのものがそのまま引き継がれるので、HelloLibではWebページの本体のみ作成します。</p><p>表示したい本文を記述したページをindex.htmlとして用意します。</p><p>これは前回「Cozy Web/レイアウト」で作成したWebアプリケーション「LayoutBootstrap」と基本的に同じ内容です。(タイトルだけ変更しています)タグのクラスにBootstrapのクラスを設定しています。WebライブラリLibHelloでBootstrap 5を活用したレイアウトを設定しているので、その効果があるはずです。</p><pre class="java" name="code"><html>
<head>
<title>HelloLib</title>
</head>
<body>
<h1>HelloLib</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloLib を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloLib/
</pre><p>取得結果は以下になります。無事、登録したHTML文書にBootstrapの各種設定を行ったHTML文書を取得することができました。</p><pre class="java" name="code"><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<title>HelloLib</title>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<header>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto">
<div class="row flex-grow-sm-1 flex-grow-0">
<aside class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3">
<div class="bg-light border p-1 h-100 sticky-top">
<ul class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate">
<li class="nav-item">
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-house fs-5"></i>
<span class="d-none d-sm-inline">Home</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-speedometer fs-5"></i>
<span class="d-none d-sm-inline">Dashboard</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-card-text fs-5"></i>
<span class="d-none d-sm-inline">Orders</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-bricks fs-5"></i>
<span class="d-none d-sm-inline">Products</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-people fs-5"></i>
<span class="d-none d-sm-inline">Customers</span>
</a>
</li>
</ul>
</div>
</aside>
<main class="col overflow-auto h-100">
<h1>HelloLib</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</main>
</div>
</div>
<footer>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</footer>
</body>
</html>
</pre><p>このページは以下のように表示されます。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbicnWEByKZ84LUoVD-S7LrwE2ZjU0zpeGoMSlI6QpS5LZUVkFFED2THfzoSoHBSvYNh3QXjFeziUi3-r70Bm8d78MpccGqrz7l8WgV1A783uJBUtm8_BiaLh6xD7g1-tJmHgBeGR32HcNYyUp2-eZxRZ-FTjHisw3eLMyy52kZoPYWMWDE339PFFG/s4086/Large.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1558" data-original-width="4086" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbicnWEByKZ84LUoVD-S7LrwE2ZjU0zpeGoMSlI6QpS5LZUVkFFED2THfzoSoHBSvYNh3QXjFeziUi3-r70Bm8d78MpccGqrz7l8WgV1A783uJBUtm8_BiaLh6xD7g1-tJmHgBeGR32HcNYyUp2-eZxRZ-FTjHisw3eLMyy52kZoPYWMWDE339PFFG/s320/Large.jpg"/></a></div>
<p>Bootstrapの機能を活かしたレイアウト、カラーコーディネーションになっています。</p><p>小さな画面で表示すると、以下のようにメニューが折り畳まれて表示されます。Bootstrapのレシポンシブデザインが効いていることが分かります。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYtNCgR6IL3_WomiouR-VC4hSksOKy2yOKpF8qrgurUJWvG8dhJlM3y8Zq8z_vpQuHgOHJFZrzxH6v90Kbc0UwLx6WLXeCrgMB38NcjGUG2j5hK74Fbmu3n7At_e9o_4B9ThvoWOEiQdx0ZcJISPAQMrMW-nGfnNvI9lWo57lJpLNGlAni3ovbv9u2/s2998/Small.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1558" data-original-width="2998" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYtNCgR6IL3_WomiouR-VC4hSksOKy2yOKpF8qrgurUJWvG8dhJlM3y8Zq8z_vpQuHgOHJFZrzxH6v90Kbc0UwLx6WLXeCrgMB38NcjGUG2j5hK74Fbmu3n7At_e9o_4B9ThvoWOEiQdx0ZcJISPAQMrMW-nGfnNvI9lWo57lJpLNGlAni3ovbv9u2/s320/Small.jpg"/></a></div>
<p>いずれも前回のLayoutBootstrapとタイトルを除いては同じ動きです。</p></section><section><h3>効果</h3><p>WebアプリケーションHelloLibで用意したファイルはindex.htmlのみです。</p><p>HelloLibはWebライブラリLibHelloを引き継いでいるので、LibHelloが提供しているBootstrapの機能を活かした共有レイアウトをそのまま利用できています。</p></section></section><section><h2>まとめ</h2><p>今回はWebアプリケーションの共通テンプレートをWebライブラリという形の部品として作成し、Webアプリケーションで使用する方法について説明しました。</p><p>Bootstrapベースで、ヘッダやフッタのレイアウトを共通テンプレートとしたWebライブラリHelloLibを作成しました。</p><p>このWebライブラリを使用することで、WebアプリケーションHelloLibはHTML文書index.htmlを作成するだけで、HelloLibが提供しているBootstrapベースの共通レイアウトを使用したリッチな画面を得ることができました。</p><p>Cozy WebのWebライブラリ機能を使用することで、Webアプリケーションの開発効率を飛躍的に向上させることができます。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.6</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-30608427808581656792022-07-31T20:00:00.001+09:002022-07-31T20:00:00.180+09:00Cozy Web/レイアウト<div><p>前回「Cozy Web/Bootstrap」ではBootstrapのテンプレートを使用するためにレイアウト機能を使用しました。</p><p>今回は、このCozy Webのレイアウト機能について少し詳しく説明します。</p><section><h2>HelloLayout</h2><p>まず、レイアウト機能を使ったHelloLayoutアプリケーションを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloLayoutを作成します。このディレクトリHelloLayoutをアプリケーションのホームディレクトリとなります。</p></section><section><h3>共通テンプレート</h3><p>Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。</p><pre class="java" name="code">-@val model: ViewModel
!!! 5
html(lang="ja")
head
=model.pageTitle
body
=model.header
=model.navigation
=model.sidebar
=model.content
=model.footer
</pre><p>headに以下の設定があります。</p><pre class="java" name="code"> =model.pageTitle
</pre><p>ページのタイトルをhead要素の配下に追加する指定になります。</p><p>またbodyに以下の設定があります。</p><pre class="java" name="code"> =model.header
=model.navigation
=model.sidebar
=model.content
=model.footer
</pre><p>それぞれ以下の部品をbody要素の配下に追加する指定です。</p><dl><dt>model.header</dt><dd>ページのヘッダー</dd><dt>model.navigation</dt><dd>ナビゲーション・バー</dd><dt>model.sidebar</dt><dd>サイド・バー</dd><dt>model.content</dt><dd>ページの本文</dd><dt>model.footer</dt><dd>ページのフッター</dd></dl><p>ヘッダー、フッター、ナビゲーション・バー、サイド・バーで構成される固定レイアウト内に本文を埋め込む構成になっています。</p></section><section><h3>部品ページ</h3><p>Webページの部品はWEB-INF/partialsに格納します。</p><p>partialsに格納する部品は、header.htmlやheader.jadeのようにファイル名本体を部品名とします。サフィックスは部品の記述を行う言語になります。</p><section><h4>ヘッダー</h4><p>ヘッダーとして以下のheader.jadeをWEB-INF/partialsに格納しました。</p><pre class="java" name="code">div Header
</pre></section><section><h4>ナビゲーション・バー</h4><p>ナビゲーション・バーとして以下のnavigation.jadeをWEB-INF/partialsに格納しました。</p><pre class="java" name="code">div Navigation
</pre></section><section><h4>フッター</h4><p>フッターとして以下のfooter.jadeをWEB-INF/partialsに格納しました。</p><pre class="java" name="code">div Footer
</pre></section><section><h4>サイド・バー</h4><p>フッターとして以下のsidebar.jadeをWEB-INF/partialsに格納しました。</p><pre class="java" name="code">div Sidebar
</pre></section></section><section><h3>Webページ</h3><p>WebアプリケーションのWebページとしてindex.htmlを用意します。</p><p>後述のBootstrap版との比較のために、Bootstrapのクラスを用いた同じWebページを用いています。この版ではBootstrapの設定は行っていないので、画面表示に影響しません。</p><pre class="java" name="code"><!doctype html>
<html>
<head>
<title>HelloLayout</title>
</head>
<body>
<h1>HelloLayout</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloLayout/を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloLayoutが、先程作成したディレクトリHelloLayoutに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloLayout/
</pre><p>取得結果は以下になります。無事登録したHTML文書を取得することができました。</p><p>HTML文書には期待通りLayoutの各種設定が自動的に行われています。</p><pre class="java" name="code"><!DOCTYPE html>
<html lang="ja">
<head>
<title>HelloLayout</title>
</head>
<body>
<div>Header</div>
<div>Navigation</div>
<div>Sidebar</div>
<h1>HelloLayout</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
<div>Footer</div>
</body>
</html>
</pre><p>このページは以下のように表示されます。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Zz79T8z5w9z-dtdBMOEPdjiOLKEogdwS_VxZrYpKdl3ubVThGy9_gFyG4_NKWP76-c6PdVrA9cKu1ytK0DKQ8s3azXkO6dLhfnZi7qk8nz464yET16Edai9NAjOGtyvYpsIAgbpx9qMI0Y3DY9RGpNmtfdkZwR01aGD6xVqDXZqqi0rnCxtPbXbG/s4010/HelloLayout.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1718" data-original-width="4010" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1Zz79T8z5w9z-dtdBMOEPdjiOLKEogdwS_VxZrYpKdl3ubVThGy9_gFyG4_NKWP76-c6PdVrA9cKu1ytK0DKQ8s3azXkO6dLhfnZi7qk8nz464yET16Edai9NAjOGtyvYpsIAgbpx9qMI0Y3DY9RGpNmtfdkZwR01aGD6xVqDXZqqi0rnCxtPbXbG/s320/HelloLayout.jpg"/></a></div>
</section></section><section><h2>LayoutBootstrap</h2><p>レイアウト機能を使うと、定形のWebページ内に定義した部品を差し込める事が分かりました。</p><p>このレイアウト機能を使って、Bootstrapベースの定形ページを作ってみます。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリLayoutBootstrapを作成します。このディレクトリLayoutBootstrapをアプリケーションのホームディレクトリとなります。</p></section><section><h3>共通テンプレート</h3><p>Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。このテンプレートページでBootstrapに必要な設定を行っています。</p><pre class="java" name="code">-@val model: ViewModel
!!! 5
html(lang="ja")
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1")
link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous")
=model.pageTitle
body
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous")
header
=model.header
=model.navigation
div(class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto")
div(class="row flex-grow-sm-1 flex-grow-0")
aside(class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3")
div(class="bg-light border p-1 h-100 sticky-top")
=model.sidebar
main(class="col overflow-auto h-100")
=model.content
footer
=model.footer
</pre></section><section><h3>部品ページ</h3><p>Webページの部品はWEB-INF/partialsに格納します。</p><section><h4>ヘッダー</h4><p>ヘッダーとして以下のheader.jadeをWEB-INF/partialsに格納しました。</p><p>Bootstrapのクラスを設定しています。</p><pre class="java" name="code">nav(class="navbar navbar-light bg-primary")
div(class="container-fluid")
span(class="navbar-brand mb-0 h1") Cozy Web
</pre></section><section><h4>ナビゲーション・バー</h4><p>ナビゲーション・バーとして以下のnavigation.jadeをWEB-INF/partialsに格納しました。</p><p>Bootstrapの機能を用いてナビゲーション・バーを実現しています。</p><pre class="java" name="code">nav(class="navbar navbar-expand-lg navbar-light bg-light")
div(class="container-fluid")
a(class="navbar-brand" href="#") Navbar
button(class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation")
span(class="navbar-toggler-icon")
div(class="collapse navbar-collapse" id="navbarNav")
ul(class="navbar-nav")
li(class="nav-item")
a(class="nav-link active" aria-current="page" href="#") Home
li(class="nav-item")
a(class="nav-link" href="#") Features
li(class="nav-item")
a(class="nav-link" href="#") Pricing
li(class="nav-item")
a(class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true") Disabled
</pre></section><section><h4>フッター</h4><p>フッターとして以下のfooter.jadeをWEB-INF/partialsに格納しました。</p><p>Bootstrapのクラスを設定しています。</p><pre class="java" name="code">nav(class="navbar navbar-light bg-secondary")
span Cozy Web
</pre></section><section><h4>サイド・バー</h4><p>サイド・バーとして以下のsidebar.jadeをWEB-INF/partialsに格納しました。</p><p>Bootstrapの機能を用いてサイド・バーを実現しています。</p><pre class="java" name="code">ul(class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate")
li(class="nav-item")
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-house fs-5")
span(class="d-none d-sm-inline") Home
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-speedometer fs-5")
span(class="d-none d-sm-inline") Dashboard
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-card-text fs-5")
span(class="d-none d-sm-inline") Orders
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-bricks fs-5")
span(class="d-none d-sm-inline") Products
li
a(href="#" class="nav-link px-2 text-truncate")
i(class="bi bi-people fs-5")
span(class="d-none d-sm-inline") Customers
</pre></section></section><section><h3>Webページ</h3><p>表示したい本文を記述したページをindex.htmlとして用意します。</p><p>これは前出のHelloLayout版と基本的に同じ内容です。(タイトルだけ変更しています)今度はBootstrapのクラス指定が活きてくるはずです。</p><pre class="java" name="code"><!doctype html>
<html>
<head>
<title>LayoutBootstrap</title>
</head>
<body>
<h1>LayoutBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/LayoutBootstrap を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/LayoutBootstrap/
</pre><p>取得結果は以下になります。無事、登録したHTML文書にBootstrapの各種設定を行ったHTML文書を取得することができました。</p><pre class="java" name="code"><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<title>LayoutBootstrap</title>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<header>
<nav class="navbar navbar-light bg-primary">
<div class="container-fluid">
<span class="navbar-brand mb-0 h1">Cozy Web</span>
</div>
</nav>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
<li class="nav-item">
<a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<div class="container-fluid pb-3 flex-grow-1 d-flex flex-column flex-sm-row overflow-auto">
<div class="row flex-grow-sm-1 flex-grow-0">
<aside class="col-sm-3 flex-grow-sm-1 flex-shrink-1 flex-grow-0 sticky-top pb-sm-0 pb-3">
<div class="bg-light border p-1 h-100 sticky-top">
<ul class="nav nav-pills flex-sm-column flex-row mb-auto justify-content-between text-truncate">
<li class="nav-item">
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-house fs-5"></i>
<span class="d-none d-sm-inline">Home</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-speedometer fs-5"></i>
<span class="d-none d-sm-inline">Dashboard</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-card-text fs-5"></i>
<span class="d-none d-sm-inline">Orders</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-bricks fs-5"></i>
<span class="d-none d-sm-inline">Products</span>
</a>
</li>
<li>
<a href="#" class="nav-link px-2 text-truncate">
<i class="bi bi-people fs-5"></i>
<span class="d-none d-sm-inline">Customers</span>
</a>
</li>
</ul>
</div>
</aside>
<main class="col overflow-auto h-100">
<h1>LayoutBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</main>
</div>
</div>
<footer>
<nav class="navbar navbar-light bg-secondary">
<span>Cozy Web</span>
</nav>
</footer>
</body>
</html>
</pre><p>このページは以下のように表示されます。</p><p>Bootstrapの機能を活かしたレイアウト、カラーコーディネーションになっています。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkrJ1cjxcUvOUfCZ_KgvaHOXRPq_FT2FeF_374_nxY8T-dZRveKItf6Ep3p22eqJrmuJt-7G81ZhV3CZJFSzgk65ha3dMUbV1SXfSMdX6EVIWaljjMro1wpwN8mK8U-3JOoBx_QQk_Df0fx-YGrdd4L6mBTSCivgxjxCEZJmCFrjJqTsWQWqQcHbaT/s4010/LayoutBootstrap.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1718" data-original-width="4010" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkrJ1cjxcUvOUfCZ_KgvaHOXRPq_FT2FeF_374_nxY8T-dZRveKItf6Ep3p22eqJrmuJt-7G81ZhV3CZJFSzgk65ha3dMUbV1SXfSMdX6EVIWaljjMro1wpwN8mK8U-3JOoBx_QQk_Df0fx-YGrdd4L6mBTSCivgxjxCEZJmCFrjJqTsWQWqQcHbaT/s320/LayoutBootstrap.jpg"/></a></div>
<p>小さな画面で表示すると、以下のようにメニューが折り畳まれて表示されます。Bootstrapのレシポンシブデザインが効いていることが分かります。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmeKiRyfFsWRVIm1bKg_EXtPslf8w5MOeDXiBA201i7ETeDEcemEidn5hamvyb0BDtWBdrSAcDobgZI4Ol4RDxymqpKoF-2JfVp_7hfDB42WBV_XX3UME9T_YPw4KcyXiwwuvv5DpgbcCA82ImMkcAMmnknyvs9Bxx1x-P-NqSUlHJq1YuMrCV13ID/s2494/LayoutBootstrapSmall.jpg" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1722" data-original-width="2494" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmeKiRyfFsWRVIm1bKg_EXtPslf8w5MOeDXiBA201i7ETeDEcemEidn5hamvyb0BDtWBdrSAcDobgZI4Ol4RDxymqpKoF-2JfVp_7hfDB42WBV_XX3UME9T_YPw4KcyXiwwuvv5DpgbcCA82ImMkcAMmnknyvs9Bxx1x-P-NqSUlHJq1YuMrCV13ID/s320/LayoutBootstrapSmall.jpg"/></a></div>
</section></section><section><h2>まとめ</h2><p>Cozy Webのレイアウト機能について説明しました。</p><p>BootstrapのようなWebフレームワークの定形テンプレートを容易に作成することができます。</p><p>次回は、定形テンプレートをさらに部品化する方法について説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.6</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-41765246341639062562022-06-30T20:00:00.001+09:002022-06-30T20:00:00.159+09:00Cozy Web/Bootstrap<div><p>BootstrapはレスポンシブWebデザインを可能にするWebフレームワークです。</p><p>Bootstrapを使う場合、Webの全ページにBootstrapの設定を行う必要がありますが、これを手作業で行うと大変です。</p><p>Cozy Webでは、共通のページレイアウトを設定して、これを必要な全ページに自動的に適用する機能を提供しています。この機能を用いてBootstrapのWebページを作成してみます。</p><section><h2>HelloBootstrap</h2><p>Bootstrapを用いたWebアプリケーションHelloBootstrapを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloBootstrapを作成します。このディレクトリHelloBootstrapをアプリケーションのホームディレクトリとなります。</p></section><section><h3>共通テンプレート</h3><p>Webページで共有されるテンプレートとして以下のものをWEB-INF/layouts/default.jadeに作成します。</p><p>Bootstrapの本体はCDN上に公開されているものを使用する設定になっています。</p><pre class="java" name="code">-@val model: ViewModel
!!! 5
html(lang="ja")
head
meta(charset="utf-8")
meta(name="viewport" content="width=device-width, initial-scale=1")
link(href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous")
=model.pageTitle
body
script(src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous")
=model.content
</pre><p>ポイントは以下の2つの設定です。</p><pre class="java" name="code"> =model.pageTitle
</pre><pre class="java" name="code"> =model.content
</pre><p>前者はページのタイトルをhead要素内に設定します。</p><p>後者はページの内容をbody要素内に展開します。</p><p>なお、ここではJadeを用いてページの定義をしていますが、HTMLやSSPを用いてもかまいません。</p><p>共通テンプレートはタグ混じりの本文文書がなく、タグによる骨格だけの文書になるので、Jadeでは構造を簡潔に見通しよく記述できるためJadeを採用しました。</p></section><section><h3>Webページ</h3><p>WebアプリケーションのWebページとしてindex.htmlを用意します。</p><pre class="java" name="code"><html>
<head>
<title>HelloBootstrap</title>
</head>
<body>
<h1>HelloBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>このページにはBootstrapの設定はありませんが、table要素のclass属性にBootstrapの定義するクラスであるtableを使用しています。</p></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloBootstrap/を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloBootstrapが、先程作成したディレクトリHelloBootstrapに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloBootstrap/
</pre><p>取得結果は以下になります。無事登録したHTML文書を取得することができました。</p><p>HTML文書には期待通りBootstrapの各種設定が自動的に行われています。</p><pre class="java" name="code"><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<h1>HelloBootstrap</h1>
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>このページは以下のように表示されます。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ-pZX5TBjVtjwkF5-W1NPxv3nzia0BZvuCWHsawFZSUMmkUfm9vXYRYF3H5bq1rEmcI7th1VbbpYQ5_79SSV3EFKN88Frr5K9rI2c8JBuXyTDppAHpBwcWVHvXit9qfUgiiTjw69ckwCcRVrrUp0qcwFHXOD-iwhnhVHHFxuZRxZ2FcsUZbBLTh95/s1880/index.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1022" data-original-width="1880" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQ-pZX5TBjVtjwkF5-W1NPxv3nzia0BZvuCWHsawFZSUMmkUfm9vXYRYF3H5bq1rEmcI7th1VbbpYQ5_79SSV3EFKN88Frr5K9rI2c8JBuXyTDppAHpBwcWVHvXit9qfUgiiTjw69ckwCcRVrrUp0qcwFHXOD-iwhnhVHHFxuZRxZ2FcsUZbBLTh95/s320/index.png"/></a></div>
</section></section><section><h2>次の例</h2><p>次の例として以下のHTML文書をrich-table.htmlとして用意します。</p><p>このHTML文書では、table要素のclass属性にBootstrapの定義するクラスであるtable, table-striped, table-hoverを使用しています。</p><p>またtr要素のclass属性にBootstrapの定義するクラスであるtable-primaryを使用しています。</p><pre class="java" name="code"><html>
<head>
<title>Rich Table</title>
</head>
<body>
<h1>Rich Table</h1>
<table class="table table-striped table-hover">
<thead>
<tr class="table-primary">
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の/web/HelloBootstrap/rich-table を取得します。</p><pre class="java" name="code">$ curl http://localhost:8080/web/HelloBootstrap/rich-table
</pre><p>取得結果は以下になります。無事、登録したHTML文書にBootstrapの各種設定を行ったHTML文書を取得することができました。</p><pre class="java" name="code"><!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta content="width=device-width, initial-scale=1" name="viewport" />
<link crossorigin="anonymous" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" />
<title>Rich Table</title>
</head>
<body>
<script crossorigin="anonymous" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<h1>Rich Table</h1>
<table class="table table-striped table-hover">
<thead>
<tr class="table-primary">
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</body>
</html>
</pre><p>このページは以下のように表示されます。</p>
<div class="separator" style="clear: both;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyBrTqdMRB79FVNVlwkeXIO0KNa4df-CmmrLB5-STMhAn97Hq9faWKmsp74ENaED0jmsMCv7ne6b760sZHgDgzCJIZyYbaF-gWVryW43Pd04CA171kO0n3JjnwJn_P6c9whhcKom1vBk0aKv24UDJJExGlAQAXBQja3-3Esxb5jyPID0YvhG8DD15v/s1880/rich-table.png" style="display: block; padding: 1em 0; text-align: center; "><img alt="" border="0" width="320" data-original-height="1022" data-original-width="1880" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyBrTqdMRB79FVNVlwkeXIO0KNa4df-CmmrLB5-STMhAn97Hq9faWKmsp74ENaED0jmsMCv7ne6b760sZHgDgzCJIZyYbaF-gWVryW43Pd04CA171kO0n3JjnwJn_P6c9whhcKom1vBk0aKv24UDJJExGlAQAXBQja3-3Esxb5jyPID0YvhG8DD15v/s320/rich-table.png"/></a></div>
</section></section><section><h2>まとめ</h2><p>今回はCozy Webの共通テンプレート機能を用いて、Bootstrapを用いたWebアプリケーションを作成しました。</p><p>特にコントローラの設定も不要で、単に共通テンプレートを所定の場所に置くだけで、Webアプリケーションのページに共通の設定を行うことができました。</p><p>次回は共通テンプレートを使って、ページに共通構造を導入してみます。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.6</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-35239448510572396862022-05-31T18:00:00.001+09:002022-05-31T18:00:00.159+09:00Cozy Web/Controller<div><p>Webアプリケーションでは、リクエストに対する動的な振る舞いを実現する必要があります。このためのメカニズムとしてCozy Webでは、Webパイプラインというメカニズムを用意しています。</p><p>Webパイプラインでは複数のモジュールをパイプライン上に配置しますが、振る舞いを記述するためのモジュールとしてパイプライン上で動作するコントローラを使用します。</p><p>今回はコントローラを用いてページの振る舞いを記述する基本的な方法について説明します。</p><section><h2>HelloController</h2><p>コントローラを使用するWebアプリケーションHelloControllerを作成します。</p><section><h3>準備</h3><p>cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloControllerを作成します。このディレクトリHelloControllerをアプリケーションのホームディレクトリとなります。</p></section><section><h3>Webページ</h3><p>コントローラによって生じる振る舞いを表示するためのWebページとして以下のindex.htmlを用意します。</p><pre class="java" name="code"><html>
<head>
<title>HelloController</title>
</head>
<body>
<p><c:value name="a"/></p>
</body>
</html>
</pre><p>拡張タグvalue「<c:value name="a"/>」によって、プロパティ「a」の内容を表示します。</p><p>このindex.htmlをHelloControlerディレクトリに配備します。</p></section><section><h3>Controller</h3><p>次はコントローラの設定です。</p><p>まずコントローラに設定するアクションとして、以下のプロパティaに値を設定するアクションを作成します。</p><pre class="java" name="code">{
"action": "property",
"properties": [{
"name" : "a",
"value" : 5
}]
}
</pre><p>このアクションをコントローラに登録するために、ホームディレクトリ配下のWEB-INF/controllersディレクトリにindex.jsonの名前で保存します。</p><p>index.jsonの名前はindex.html表示前に起動されるコントローラに登録されるアクションであることを示しています。</p><p>これでアプリケーションの作成は完了です。</p></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の /web/HelloTag/index.html を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloTagが、先程作成したディレクトリHelloTagに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">curl -v http://localhost:8080/web/HelloTag/index.html
</pre><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><pre class="java" name="code">* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET /web/HelloController/index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sun, 29 May 2022 02:41:41 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.4.38.v20210224)
<
<!DOCTYPE html>
<html><head>
<title>HelloController</title>
</head><body>
<p>5</p>
</body></html>
* Connection #0 to host localhost left intact
</pre><p>無事、プロパティaの値として設定した「5」がWebページ上に表示されました。</p></section></section><section><h2>Webページの種類</h2><p>HTML文書index.htmlはコントローラで設定したプロパティを表示します。</p><p>HTML文書以外のフォーマットでも、同一のコントローラに対して動作します。</p><p>このindex.htmlと同等の各種フォーマットは以下のとおりです。</p><section><h3>Jade</h3><p>Jade文書では、serviceにバインドされたViewService経由でプロパティを取得します。</p><pre class="java" name="code">-@val service: ViewService
html
head
title HelloController
body
p =service.get("a")
</pre><p>アプリケーションに配備する場合にはindex.jadeで保存します。</p></section><section><h3>Jade&タグ</h3><p>Jade文書でも拡張タグを用いることができます。この場合はViewServiceを直接使用する必要はありません。</p><pre class="java" name="code">html
head
title HelloController
body
p<
c:value(name="a")
</pre><p>アプリケーションに配備する場合にはindex.jadeで保存します。</p></section><section><h3>SSP</h3><p>SSP文書でも、serviceにバインドされたViewService経由でプロパティを取得します。</p><pre class="java" name="code"><%@ val service: ViewService %>
<html>
<head>
<title>HelloController</title>
</head>
<body>
<p><%= service.get("a") %></p>
</body>
</html>
</pre><p>アプリケーションに配備する場合にはindex.sspで保存します。</p></section><section><h3>SSP&タグ</h3><p>SSP文書でも拡張タグを用いることができます。この場合はViewServiceを直接使用する必要はありません。</p><pre class="java" name="code"><html>
<head>
<title>HelloController</title>
</head>
<body>
<p><c:value name="a"/></p>
</body>
</html>
</pre><p>アプリケーションに配備する場合にはindex.sspで保存します。</p><p>HTML文書+拡張タグに加えて、Jade文書、Jade文書+拡張タグ、SSP文書、SSP文書+拡張タグのいずれも、同一のコントローラ用のアクションindex.jspで同じ表示をします。ページ表示に必要なデータ生成部と、表示用のビュー部の独立性が保たれていることが分かります。</p></section></section><section><h2>まとめ</h2><p>今回はCozy WebでWebアプリケーションの振る舞いを制御するコントローラの基本的な使い方について説明しました。</p><p>JSON文書でコントローラに設定するアクションを記述し、WEB-INF/controllerに配備することでコントローラの設定を行うことができます。</p><p>コントローラで生成したデータはHTML文書などのビュー上に配置した拡張タグで表示することができます。</p><p>今回のコントローラはプロパティ設定のアクションなので動作もシンプルですが、Form処理などの複雑な処理もアクション設定のみで使用できるようになります。</p><p>次回はBootstrapを使ったWebアプリケーションをCozy Webで実現する方法を取り上げる予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.6</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-40705409668244569882022-04-30T20:14:00.000+09:002022-04-30T20:14:38.433+09:00Cozy Web/Tag<div><p>前回紹介したとおりCozy WebではHTMLページを動的に生成するための機能として、テンプレートエンジンScalateによるSspやJade(Pug)を提供しています。</p><p>SspやJadeでは、基本的にプログラミング言語の断片をHTMLに埋め込む形になります。プログラミング機能をフルに使えるので、リッチな動的コンテンツを作成できるというメリットがある反面おまじない的なコードが必要になったり、アプリケーションロジックがプレゼンテーション層であるWebページに混入しがちになるといった問題がでてきます。</p><p>この問題に対してCozy Webではタグ機能を用意しました。タグ機能はCozy Webが提供する様々な機能をビュー層で簡単に使えるようにするための機能を提供します。拡張タグをHTML内に埋め込むことで、HTMLページの動的機能を簡単に実現することができます。</p><section><h2>SSP</h2><p>まずSSPによる動的ページについて確認しておきましょう。</p><p>以下はSSPによる動的ページです。</p><pre class="java" name="code"><%@ var context: ViewContext %>
<html>
<head>
<title>HelloTag</title>
</head>
<body>
<p>現在の時刻は${context.datetime}です。</p>
</body>
</html>
</pre><p>まずページ内で使用する変数として、以下の行でViewContextを格納する変数contextを定義しています。</p><pre class="java" name="code"><%@ var context: ViewContext %>
</pre><p>そして、以下の行でViewContextオブジェクトのdateTimeメソッドを呼び出し、その結果をpタグ内の文章に埋め込んでいます。dateTimeメソッドは現在時刻をロケール、タイムゾーンに対応した文字列で返します。</p><pre class="java" name="code"> <p>現在の時刻は${context.dateTime}です。</p>
</pre></section><section><h2>HelloTag</h2><p>Cozy Webのタグを使用したWebアプリケーションHelloTagを作成します。</p><section><h3>アプリケーション</h3><p>以下のHTMLはCozy Webタグを使用して前出のSSPと同じ動作をします。</p><pre class="java" name="code"><html>
<head>
<title>HelloTag</title>
</head>
<body>
<p>現在の時刻は<c:datetime/>です。</p>
</body>
</html>
</pre><p>以下の行で現在時刻を埋め込みたい場所にタグc:datetime配置しています。Cozy WebではHTML内に配置されたc:datetimeを現在時刻に変換します。</p><pre class="java" name="code"> <p>現在の時刻は<c:datetime/>です。</p>
</pre><p>SSPなどのようなプログラミング成分はなく、動的なコンテンツ部分を宣言的に定義することができます。</p></section><section><h3>配備</h3><p>cozyを起動するディレクトリにwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloTagを作成します。</p><p>このHelloTagディレクトリに前述のindex.htmlを作成すればOKです。</p></section><section><h3>起動</h3><p>Cozyをwebコマンドで起動するとWebプラットフォームとして起動します。</p><pre class="java" name="code">$ cozy web
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の /web/HelloTag/index.html を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloTagが、先程作成したディレクトリHelloTagに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">curl -v http://localhost:8080/web/HelloTag/index.html
</pre><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><pre class="java" name="code">> GET /web/HelloTag/index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Sat, 30 Mar 2022 18:30:00 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.4.38.v20210224)
<
<!DOCTYPE html>
<html>
<head>
<title>Hello Tag</title>
</head>
<body>
<p>現在の時刻は2022年4月30日18時30分00秒です。</p>
</body>
</html>
</pre></section></section><section><h2>まとめ</h2><p>今回はCozy WebのTag機能を説明しました</p><p>Tag機能を使えば、通常のHTMLにタグを埋め込むだけで動的コンテンツのWebページを作成することができます。</p><p>次回は動的コンテンツを実現する要の機能であるコントローラー機能を説明します。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.5</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-63727991813491627962022-03-31T18:00:00.025+09:002022-03-31T18:00:00.175+09:00Cozy Web/HTMLフォーマット<div><p>Cozy Webでは通常のHTMLに加えて、以下の4つのフォーマットをサポートしています。</p><dl><dt>Mustache</dt><dd>Mustache派生の独自マークアップ</dd><dt>Scaml</dt><dd>HamlのScala版</dd><dt>Jade</dt><dd>Pug派生の独自マークアップ</dd><dt>Ssp</dt><dd>VelocityやJSPなどのHTML埋め込みフォーマットのScala版</dd></dl><p>これらのフォーマットはテンプレートエンジン<a href="https://scalate.github.io/scalate/">Scalate</a>を使用して実現しており、フォーマットの仕様はScalateの提供するものになります。</p><p>今回はこの中でSspとJadeの2つのフォーマットを使ったWebページを試してみます。</p><section><h2>HelloSsp</h2><p>Ssp(Scala Server Pages)はVeloicyやJSPなどと同系統のHTMLにマークアップするフォーマットです。Scalate独自のフォーマットで、埋め込みプログラミング言語にScalaを使用しています。</p><p>HTMLをベースに必要箇所だけマークアップする方式なので習得が容易です。またお勧めはできませんが、プログラミング言語によるロジックをマークアップで記述することが可能です。</p><section><h3>アプリケーション</h3><p>以下のindex.sspを用意します。</p><p>基本的に通常のHTMLで、"${"と"}"で囲まれた「new java.util.Date()」がScala言語の埋め込み部分です。</p><pre class="java" name="code"><html>
<head>
<title>Hello SSP!</title>
</head>
<body>
<h1>Hello SSP!</h1>
<p>今日は ${new java.util.Date()} です。</p>
</body>
</html>
</pre></section><section><h3>配備</h3><p>cozyを起動するディレクトリにwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloSspを作成します。</p><p>このHelloSspディレクトリに前述のindex.sspを作成すればOKです。</p></section><section><h3>起動</h3><p>Cozyをwebコマンドで起動するとWebプラットフォームとして起動します。</p><pre class="java" name="code">$ cozy web
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の /web/HelloSsp/index.html を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloSspが、先程作成したディレクトリHelloSspに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">curl -v http://localhost:8080/web/HelloSsp/index.html
</pre><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><pre class="java" name="code">> GET /web/HelloSsp/index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 28 Mar 2022 22:02:47 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.4.38.v20210224)
<
<!DOCTYPE html>
<html>
<head>
<title>Hello SSP!</title>
</head>
<body>
<h1>Hello SSP!</h1>
<p>今日は 2022年3月29日 です。</p>
</body>
</html>
</pre></section></section><section><h2>HelloJade</h2><p>SspはHTMLをベースにマークアップを入れる方式なので習得も容易ですが、HTML言語から引き継いでいる特性としてマークアップがやや煩雑です。</p><p>文章の中にマークアップする場合にはHTML言語が適していますが、HTML文書の構造などを記述する場合には冗長な表現になりがちです。</p><p>Jadeはタグの木構造を簡潔に記述することに適したフォーマットです。Jadeは現在ではPug( <a href="https://pugjs.org/">https://pugjs.org/</a> )と変名されていますが、ここではScalateの用語法を踏襲してJadeを使用します。Jadeはタグの木構造を簡潔に記述することに適したフォーマットです。Jadeは現在ではPug( <a href="https://pugjs.org/">https://pugjs.org/</a> )と変名されていますが、ここではScalateの用語法を踏襲してJadeを使用します。</p><section><h3>アプリケーション</h3><p>以下のindex.jadeを用意します。</p><p>タグの木構造をインデントで記述します。HTML文書を簡潔に記述することができます。</p><pre class="java" name="code">html(lang="ja")
head
title Hello Jade!
body
h1 Hello Jade!
p
| 今日は
= new java.util.Date()
| です。
:markdown
Jadeを使うとMarkdownで文章を書く事ができます。
</pre></section><section><h3>配備</h3><p>cozyを起動するディレクトリにwebappsディレクトリに、アプリケーションのホームとなるディレクトリHelloJadeを作成します。</p><p>このHelloJadeディレクトリに前述のindex.jadeを作成すればOKです。</p></section><section><h3>起動</h3><p>Cozyをwebコマンドで起動するとWebプラットフォームとして起動します。</p><pre class="java" name="code">$ cozy web
</pre></section><section><h3>実行</h3><p>curlコマンドによってローカルホストの8080ポート上の /web/HelloJade/index.html を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloJadeが、先程作成したディレクトリHelloJadeに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">curl -v http://localhost:8080/web/HelloJade/index.html
</pre><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><pre class="java" name="code">* Trying ::1:8080...
* Connected to localhost (::1) port 8080 (#0)
> GET /web/HelloJade/index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Mon, 28 Mar 2022 22:04:28 GMT
< Content-Type: text/html;charset=utf-8
< Transfer-Encoding: chunked
< Server: Jetty(9.4.38.v20210224)
<
<!DOCTYPE html>
<html lang="ja">
<head>
<title>Hello Jade!</title>
</head>
<body>
<h1>Hello Jade!</h1>
<p>
今日は
2022年3月29日
です。
</p>
<p>Jadeを使うとMarkdownで文章を書く事ができます。</p>
</body>
</div>
</html>
</pre></section></section><section><h2>まとめ</h2><p>Cozy WebではHTML文書記述に以下の5つのフォーマットを使用することができます。</p><ul><li>HTML</li><li>Mustache</li><li>Scaml</li><li>Jade</li><li>Ssp</li></ul><p>前回HTML文書を使用する方法を紹介しました。</p><p>HTML文書をHTMLフォーマットで作成したものは、そのまま配備するだけでWebで表示することができます。</p><p>ただ、動的な要素を持っているページの記述の場合には動的生成が可能な文書フォーマットを使用する必要があります。Cozy WebではScalateがサポートしている4つのフォーマットが使用可能になっています。</p><p>今回は、その中のJadeとSspの2つについて使用方法を説明しました。MustacheやScamlも同様にそれぞれのフォーマットでページを記述するだけなので、簡単に使用できると思います。</p><p>次回はArcadiaが提供するタグ機能を紹介する予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.4</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0tag:blogger.com,1999:blog-7964484936470829118.post-49843426604264598392022-02-28T17:43:00.000+09:002022-02-28T17:43:51.506+09:00Cozy Web<div><p>Modegramming Styleブログではモデリングとプログラミングの一体化を指向したModegrammingというコンセプトを提唱しており、その実現のための技術体系としてSimpleModelingを整備しています。</p><p>SimpleModelingを実現するためのプラットフォームとして以下の4つのプロダクトを集約したCozyを立ち上げたことを前回ご紹介しました。</p><dl><dt><a href="https://github.com/asami/smartdox">SmartDox</a></dt><dd>文書処理系</dd><dt><a href="https://github.com/asami/simplemodeler">SimpleModeler</a></dt><dd>モデルコンパイラ</dd><dt><a href="https://github.com/asami/kaleidox">Kaleidox</a></dt><dd>アクション言語</dd><dt><a href="https://github.com/asami/arcadia">Arcadia</a></dt><dd>Webフレームワーク</dd></dl><p>CozyはGitHubで開発を進めています。</p><ul><li>https://github.com/asami/cozy</li></ul><section><h2>Cozy Web</h2><p>モデル駆動開発をWebアプリケーションまで広げるためには、モデル駆動対応したWebプラットフォームが必要です。このためのWebフレームワークとして開発を進めてきたのがArcadiaです。</p><p>CozyはこのArcadiaをベースに動作させることでモデル駆動の基盤のWebプラットフォームとして動作します。</p><p>CozyをWebプラットフォームとして動作させる形態をCozy Webと呼ぶことにします。</p></section><section><h2>HelloWorld</h2><p>Cozy Webの最小構成アプリケーションとしてHelloWorldを作成し、動作させてみます。</p><section><h3>アプリケーション</h3><p>最小構成のアプリケーションなので、index.htmlのみを配備します。以下のindex.htmlを用意します。</p><pre class="java" name="code"><html>
<head>
<title>Hello World!</title>
</head>
<body>
Hello World!
</body>
</html>
</pre></section></section><section><h2>配備</h2><p>cozyを起動するディレクトリにwebappsディレクトリを作成します。</p><p>ここにアプリケーションのホームとなるディレクトリHelloWorldを作成します。</p><p>このHelloWorldディレクトリに前述のindex.htmlを作成すればOKです。</p></section><section><h2>起動</h2><p>Cozyをwebコマンドで起動するとWebプラットフォームとして起動します。</p><pre class="java" name="code">$ cozy web
</pre></section><section><h2>実行</h2><p>curlコマンドによってローカルホストの8080ポート上の /web/HelloWorld/index.html を取得します。</p><p>/web はCozy上のWebアプリケーションのホームです。その配下のHelloWorldが、先程作成したディレクトリHelloWorldに対応するもので、ディレクトリ名がアプリケーション名になっています。</p><pre class="java" name="code">curl -v http://localhost:8080/web/HelloWorld/index.html
</pre><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><p>取得結果は以下になります。無事登録したHTMLファイルを取得することができました。</p><p>-vスイッチが指定されているので、HTTPのプロトコルヘッダーも表示されています。</p><pre class="java" name="code">> GET /web/HelloWorld/index.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.76.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 27 Feb 2022 04:12:53 GMT
< Content-Type: text/html;charset=utf-8
< Cache-Control: public,max-age=86400
< Expires: Mon, 28 Feb 2022 04:12:59 GMT
< Content-Length: 337
< Server: Jetty(9.4.38.v20210224)
<
<html>
<head>
<title>Hello World!</title>
</head>
<body>
Hello World!
</body>
</html>
</pre></section><section><h2>まとめ</h2><p>今回はモデル駆動開発向けのWebプラットフォームCozy Webを紹介しました。</p><p>ごく簡単なWebアプリケーションをHelloWorldとして配備して実行することが確認できました。</p><p>次回以降Cozy Webの機能を紹介していく予定です。</p></section><section><h2>諸元</h2><dl><dt>Cozy</dt><dd>0.0.3</dd></dl></section></div>asamihttp://www.blogger.com/profile/12083671403528595185noreply@blogger.com0