R6/R7からR8への移行

最終更新日: 2022年7月21日

複合主キー

R7.8 よりWagbyが内部で保持する複合キーの文字列表現が $ から $SEP$ に変更されました。

R7.8以前 R7.8以後
主キー1$主キー2$主キー3.. 主キー1$SEP$主キー2$SEP$主キー3..

この変更により、自動生成されるコードが変わります。これまでソースコード中にハードコードされていた"$"は、PrimaryKeyUtils.PKEY_SEPARATOR() になります。カスタマイズしたソースコード内にこの箇所があった場合、適切に置換してください。

グループの表示方法

R7.10 より、画面レイアウトにおいてグループの表示方法が未指定の場合の扱いが変わりました。

R7.10以前 R7.10以後
最初のレイアウト名は、グループの表示方法の指定にかかわらず四角で囲む。 最初のレイアウト名も、グループの表示方法の指定が有効となる。

この変更により、自動生成される JSP ファイルが変わります。

変更履歴機能のファイル型項目の扱い

R7.10より、変更履歴機能におけるファイル型項目は、実ファイル名のみが変更履歴ログに記録されるように仕様が変更されました。それまでは upload_dirを起点とする相対パス表記となっていました。

R8 へバージョンアップ後は、変更履歴機能のファイル型項目の表記が(実ファイル名のみが記録されるように)変更されます。

見た目の変更

長い文字列の折り返しルール

値部分(データ)に句読点や空白を含む文字列の場合は、折り返して表示されます。しかし区切りとなるポイントがないような文字列 (例 12345678901234567890...) は、折り返されません。

このようなデータが含まれているため折り返しが機能していないという場合は、スタイル指定でword-break: break-allを明示してください。[詳細...]

CSSによる背景色の指定

background-color ではなく background を使うようにしてください。

Wagby が利用する Dojotoolkit で、テーマが soria および nihilo で入力欄の背景色が background を使っているものがあります。そのため、これらのテーマを利用するときは background-color で指定した背景色が正しく反映されないことがあります。他のテーマを利用する場合は background-color を利用しても問題ありません。

スクリプトの変更

JavaScriptエンジンはNashornに統一

R6/R7では Java 6/7 環境を利用できたため、サーバサイドJavaScriptエンジンに Rhino を利用できました。R8 では Java 8 以上となったため、サーバサイドJavaScriptエンジンはNashornのみとなります。Rhinoを前提にしていたスクリプトはNashorn用に修正する必要があります。

importClass 宣言の修正

importClass 宣言を Java.type に置き換えます。

importClass(Packages.jp.jasminesoft.util.ExcelFunction);

は次のようになります。

var ExcelFunction = Java.type("jp.jasminesoft.util.ExcelFunction");

HSQLDBのバージョンアップによる影響

R7.10 より HSQLDB を 2.0.0 から 2.3.4 へバージョンアップしています。その影響で SELECT COUNT() の戻り値が、これまでは Integer でしたが、これが BigInteger へ変更されています。

いずれも java.lang.Number インタフェースの実装クラスですが、JavaScript での厳密等価演算子(===)利用時には注意が必要となります。

厳密等価演算子では同じ 0 という値を持っていても Integer と BigInteger は型が異なるため等価という判定とはなりません。 スクリプト内に記述した数値は Nashorn が自動的に java.lang.Double、java.lang.Long または java.lang.Integer オブジェクトとして解釈する仕様です。 https://docs.oracle.com/javase/jp/8/docs/technotes/guides/scripting/nashorn/api.html#sthref22

このため、スクリプトに次のように記載したコードは影響があります。

var recordCount = session.createSQLQuery(
   "SELECT COUNT(*) FROM \"model1\" WHERE \"pkey\" = " + pkey).uniqueResult();
if ( recordCount === 0 ) {
...

ここで「if ( recordCount === 0 ) { 」の "0" は Nashorn 側で Integer と解釈されたため、HSQLDB 2.0.0 では SELECT COUNT(*) の戻り値が同じ Integer となり、厳密等価演算子でうまく動作していましたが、HSQLDB 2.3.4 では Integer と BigInteger との比較となり等価と判定されなくなります。

対応方法

数字との比較では、厳密等価演算子を使わないことで回避できます。

if ( recordCount == 0 ) {

メール送信処理のスクリプト

R7 でメール送信のスクリプトで次のように $${{...}} と記述していた箇所を、${...} に変更してください。

旧表記

replaceMap.put("$${{message}}", "Hello Wagby");

新表記

replaceMap.put("${message}", "Hello Wagby");

カスタマイズコードの変更

Struts から Spring MVC へ (R6からの移行の場合)

R6 ではコントローラ層のフレームワークとして Struts を利用していましたが、R8 では Spring MVC に変わっています。このため次のような修正が必要です。

パッケージ名

struts という表記は controller に変わります。

R6のコード:

package jp.jasminesoft.wagby.struts.customer;

R8のコード:

package jp.jasminesoft.wagby.controller.customer;

パッケージ名を変更したとき、保存先フォルダもこれにあわせて変更してください。

ActionForward,ActionMappingの廃止

ActionForward は Struts のクラスであるため利用しません。そのため以下の行は削除します。

import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

p.mappingの廃止

ActionMapping の廃止に伴い、従来生成されていた次のコードは利用できません。

return (p.mapping.getInputForward());

代わって次のようになります。

return (getInputForward(p));

メソッドの戻り値は ActionForward ではなく String となります。詳細は R8 で生成されたコントローラクラスのソースを参考にしてください。

BaseActionの廃止

BaseActionクラスは R7.10 で廃止されました。このクラスは Struts に依存していたためです。カスタマイズコードで直接、BaseAction を利用していた場合は、次の手順に従って書き換えてください。

BaseAction.getCsvEncoding()

JfcConfigクラスが代替します。次のコードをご利用ください。

p.appctx.getBean(jp.jasminesoft.jfc.service.JfcConfig.class).getCsvEncoding()

BaseAction.getJspEncoding()

JfcConfigクラスが代替します。次のコードをご利用ください。

p.appctx.getBean(jp.jasminesoft.jfc.service.JfcConfig.class).getJspEncoding()

BaseAction.getJFCErrorManager()

BaseAction.getJFCErrorManager()は、applicationContextから取得してください。 ActionParameter クラスのインスタンス p が使える場合、次のように記述することができます。

p.appctx.getBean(JFCErrorManager.class)

ShowListXXXControllerなど、jp.jasminesoft.jfc.controller.BaseController を継承したクラスであれば、次のように記述できます。

getJFCErrorManager()

HelperやProcessBeanなどSpringのbeanとして指定されている場合、下記のようにAutowiredでbeanが作成された際にセットすることができます。

import org.springframework.beans.factory.annotation.Autowired;
...
   private JFCErrorManager errorManager;
...
   @Autowired
   public void setJFCErrorManager(JFCErrorManager errorManager) {
       this.errorManager = errorManager;
   }

BaseAction.MultiPagemapName

jp.jasminesoft.jfc.controller.BaseControllerクラスのMultiPagemapNameフィールドを利用してください。

BaseAction.isDeniedNullForwardRequestName

BaseAction に用意されていた定数は BaseController クラスが管理します。

jp.jasminesoft.jfc.controller.BaseController.isDeniedNullForwardRequestName

HibernateUtilクラスのunbindCurrentSessionメソッド

HibernateUtil#getCurrentSession() を使って、HibernateSession を取得した場合に、HibernateUtil#unbindCurrentSession() の呼び出しが必要でしたが、R8 では HibernateUtil#getCurrentSession() が廃止となったため、unbindCurrentSession() の呼び出しも不要となります。

カスタマイズコードで unbindCurrentSession() を呼び出していた部分は、R8 では何もする必要はありません。

JFCDataAccessManagerクラスのclearCountAllメソッド

R8 では JFCDataAccessManager#clearCountAll() を呼び出す処理が不要となります。

例えば次のようなコードを記述していた場合、これをそのまま削除してください。

/* R8 では不要となったコード */
JFCDataAccessManager dam =
  (JFCDataAccessManager)p.appctx.getBean(
   "JFCDataAccessManager");
if (dam == null) {
  logger.error("failed get JFCDataAccessManager");
} else {
  dam.clearCountAll(p);
}

DbActionParameter は ActionParameter へ置き換える

R8.0 よりフレームワーク内の DbActionParameter クラスが廃止され、ActionParameter となりました。R6/R7 で "p" というオブジェクトは DbActionParameter クラスのインスタンスでしたが、これが ActionParameter クラスのインスタンスになります。

型の変更

カスタマイズクラスで DbActionParameter という表記はすべて ActionParameter に変更してください。例を示します。

R6のコード:

@Override
public ActionForward do_original(DbActionParameter p)
    throws IOException, ServletException, SecurityException
{
...
}

R8のコード:

@Override
public String do_original(ActionParameter p)
    throws IOException, ServletException
{
...
}

p.con の廃止

この変更により、R6/R7 で利用できていたp.conというオブジェクトが廃止されました。

p.con の実体はデータベースコネクションオブジェクトです。カスタマイズコードで p.con を使っていた場合、これに変わる方法として HibernateUtil.openSession() を使って Hibernate Session を取得し、HQL (Hibernate で利用できるSQL) を使うように変更してください。

import jp.jasminesoft.jfc.app.HibernateUtil;
...
    {
        org.hibernate.Session session = HibernateUtil.openSession();
        String hql = ...HQLで記述されたDML...;
        Query query = session.createQuery(hql);
    }

HQL プログラミングの詳細は Hibernate のドキュメントをお読みください。Wagby R8 系に同梱されている Hibernate のバージョンは 5.1 です。

Hibernate のバージョンアップ

R8.0 に同梱される Hibernate は 5.1 となっています。旧版の Hibernate に依存していたコードがあった場合、これを 5.1 で動作するように修正してください。

プロセスビーンは EntityService へ

プロセスビーンはデータベース操作用のクラスとして提供していましたが、R8 からは EntityService を利用するようにしてください。

データの取得

R6のコード:

Customer[] customer_ary = null;
ProcessBean pbean = (ProcessBean)p.appctx.getBean("ShowListCustomerProcessBean");
pbean.setActionParameter(p);
CustomerC cond = new jp.jasminesoft.wagby.model.customer_c.CustomerC();
((CustomerCHelper)p.appctx.getBean("CustomerCHelper")).initialize(cond, p);
cond.setName(name);// ここでは顧客名を検索条件に設定した。
pbean.setParameter(ProcessBean.ConditionParamName, cond);
pbean.setParameter(ProcessBean.ReturnWrappedObjectParamName, Boolean.FALSE);
ResultBean rbean = new ResultBean();
try {
    rbean.setProcessBean(pbean);
    rbean.setSizePerPage(-1); // 無制限
    rbean.processProcessBean(p, errorManager);
    List coll = rbean.getCurrentPageItem(p, errorManager);
    if (coll != null && coll.size() > 0) {
        customer_ary = (Customer[])coll.toArray(new Customer[0]);
    }
} catch (SecurityException se) {
    logger.warn("jp.jasminesoft.wagby.app.customer.ShowListCustomerProcessBean failed.", se);
} finally {
    rbean.release();
}

R8のコード:

import jp.jasminesoft.jfc.service.JFCEntityService;
...
Customer[] customer_ary = null;
CustomerC cond = new jp.jasminesoft.wagby.model.customer_c.CustomerC();
((CustomerCHelper)p.appctx.getBean("CustomerCHelper")).initialize(cond, p);
cond.setName(name);// ここでは顧客名を検索条件に設定した。
JFCEntityService<Customer, String> entityService = 
    (JFCEntityService<Customer, String>)p.appctx.getBean("CustomerEntityService");
FinderContext<CustomerC> finderContext = new FinderContext<CustomerC>();
finderContext.setCondition(cond);
finderContext.setPageSize(-1);// 無制限
finderContext.setCriteriaConverter((CustomerCriteriaConverter)
    p.appctx.getBean("CustomerCriteriaConverter"));
List<Customer> coll = entityService.find(finderContext);
if (coll != null && coll.size() > 0) {
    customer_ary = (Customer[])coll.toArray(new Customer[0]);
}

データ1件の取得

R6のコード:

Customer customer = null;
ProcessBean _pbean = (ProcessBean)p.appctx.getBean("ShowCustomerProcessBean");
_pbean.setActionParameter(p);
_pbean.setParameter("customerid", JFCUtils.decodePrimaryKey(customerid));//主キー
Object op = null;
try {
    op = _pbean.process();
} finally {
    _pbean.release();
}
if (op == null) {
    return null;
} else if (op instanceof String) { // エラーメッセージの場合
    Object[] ep = { (String)op };
    p.errors.addJfcerror
        (errorManager.getJfcerror("error.dbaccess", ep, p.locale));
} else if (op instanceof Customer) {
    customer = (Customer)op;
}

R8のコード:

import jp.jasminesoft.jfc.service.JFCEntityService;
...
Customer customer = null;
try {
    JFCEntityService<Customer, Integer> entityService =
        (JFCEntityService<Customer, Integer>)p.appctx.getBean("CustomerEntityService");
    customer = entityService.findById(customerid, true);//主キー
} catch (Exception e) {
    String errmsg = 
        DbBaseController.convertErrorMessage(e, 
            new String[][] {
                { "customerid", JFCUtils.getRValue("customer.customerid", p.locale) }
            });
    if (errmsg == null) {
        errmsg = "";
    }
    Object[] ep = { errmsg };
    p.errors.addJfcerror
         (errorManager.getJfcerror("customer.error.dbaccess", ep, p.locale));
}

更新

R6のコード:

ProcessBean pbean = new jp.jasminesoft.wagby.app.customer.UpdateCustomerProcessBean(p);
pbean.setParameter("customer", customer);
try {
    pbean.process();
} catch (SecurityException e) {
    throw e;
} finally {
    pbean.release();
}

R8のコード:

import jp.jasminesoft.jfc.service.JFCEntityService;
...
JFCEntityService<Customer, Integer> entityService =
  (JFCEntityService<Customer, Integer>)p.appctx.getBean("CustomerEntityService");
// findById メソッドを経由してオブジェクトを取得、そのときにロックをかける。
Customer customer = entityService.findById(customerid, true);//主キー
// customer オブジェクトの内容を変更
// (省略)
// 更新
entityService.update(customer);
//entityService.update(customer, false); 未ロックのオブジェクトを更新する場合。非推奨。

更新用メソッド (update) の第一引数にはストアモデルを指定します。第二引数は更新対象モデルがロック済みかどうかを指定します。R6では未ロック状態のストアモデルを更新することができましたが、それと同じようにするためには第二引数にfalseを指定します。ただしこの方法は他ユーザによるロック取得を無視するため、推奨できません。R8へ移行時には、更新対象となるストアモデルを取得するときにロックをかけ、ロック済みのストアモデルをupdateメソッドの第一引数に指定するような見直しを行うとよいでしょう。

ジョブ定義の変更

「バッチ処理 > 自作クラスをジョブスケジューラに登録する」を行っている場合、applicationContext に登録する bean 定義ファイルに変更が生じます。Spring Framework のバージョンが 3 から 4 へバージョンアップされたため、org.springframework.scheduling.quartz.JobDetailBean クラスが廃止されました。代わりにorg.springframework.scheduling.quartz.JobDetailFactoryBean クラスを指定するようにしてください。[詳細...]

FilterManagerのbean化8.0.3

入力フィルタを管理するクラス JFCFilterManager を Spring の bean としました。この影響で FilterHelper クラスの次のメソッドが廃止されています。filter メソッドは必ず引数の最後に ActionParameter 型のインスタンス変数 p が必要となります。

  • public void filter(T t, Set<String> itemSet);
  • public void filter(T t, FilterManager filterman0, Set<String> itemSet);

開発者は customize/java/jp/jasminesoft/wagby/app/MyJFCFilterManager.java を用意することで、FilterManager クラスの getFilter メソッドをオーバーライドすることができます。

ServletContextの取得

ServletContext は次のように取得してください。

コントローラクラス

Wagbyのコントローラクラスは BaseController を継承しています。この場合は次のコードを利用できます。

getServletConfig().getServletContext()

SpringのBeanとなっているクラス

ヘルパクラスなどSpringのbeanとなっているクラスの場合、autowireでServletConfigを取得することができます。この ServletConfig から ServletContext を取得してください。

import javax.servlet.ServletConfig;
import org.springframework.beans.factory.annotation.Autowired;
...
   @Autowired
   private ServletConfig servletConfig;

内部変数 p が扱える場合

Wagby の内部変数 "p" (実体は ActionParameter クラス) が使える場合、次のコードを利用できます。

p.request.getSession().getServletContext()

ログオン画面 (logon.jsp)

R7 と R8 では logon.jsp が異なっています。R7 でログオン画面をカスタマイズして使っていた場合、その logon.jsp を R8 でお使いいただくことはできません。同じようなカスタマイズを R8 に含まれる logon.jsp に対して行ってください。

画面遷移パラメータ

condの導入

一覧表示画面に用意する独自ボタンの追加パラメータに、検索条件部の値を渡すことができるようになりました。特別表記${cond.項目名}を指定します。

これに伴い、これまで直接コンディション(のプレゼンテーション)モデルを指定してパラメータを渡していた箇所は、cond 表記に置き換えてください。

例えば、追加パラメータとして${model1_cp.item1}という表記があった場合、これを${cond.item1}としてください。

CASの設定

R7 で設定していた "CAS" による LDAP/ActiveDirectory の設定は無効になりました。本設定は R8 方式として再度、改めて行なってください。

"CAS" に代わって "Spring Security" を用います。Spring Security の詳細はこちらをお読みください。

REST API

バージョン

R7では REST API に v1 と v2 モードが存在していました。R8 では v2 モードのみとなりました。Designer で選択することはできません。

バージョン 1 (旧方式)

R7.10.3までの形式です。JSONオブジェクトのキー名はキャメルケース形式になります。

例えば項目名 "user_address" は、JSONオブジェクトのキー名が "userAddress" になります。

バージョン 2 (標準方式)

R7.11以降の形式です。JSONオブジェクトのキー名をキャメルケース形式から、項目名をそのまま出力します。

例えば項目名 "user_address" は、JSONオブジェクトのキー名も同じ "user_address" になります。

バージョン1を使う場合 [非推奨]

REST API を利用する際にHTTPヘッダ X-Wagby-RESTAPIVersion: v1 を指定することができます。この場合、モデルのREST API Version が v2 でも、このアクセスにのみ v1 を使うことができます。v1 を使う必要があるがモデル定義を変更したくない場合は、この方式をご利用ください。(ただし本方式は将来の Wagby で削除されます。あらかじめご了承ください。)

仕様変更

  • /rest/session でログオンする場合の method は PUT に変更されました。R7 までは POST でしたが、これが変わっています。

SpringBoot導入の影響

Wagby R8 は Spring Boot を組み込んでいます。この影響で R7 と変わった点は次のとおりです。

ワンポイント

Wagby の Spring Boot 対応とは、Spring Boot 形式の War ファイルを作成できるようになったという視点で行なっています。STS でアプリケーションを作成できるという意味ではありませんので、ご注意ください。(Wagby を使うため、STS で Java コードを書くというプログラミングを行うことはありません。)

動作環境

  • Designerの環境設定で、Tomcatの「JVM最大永続世代ヒープメモリサイズ」「JVM初期永続世代ヒープメモリサイズ」設定欄は廃止されました。Java8以降では利用されないためです。