概要
このページでまとめているエラーは、eclipseでSAStrutsを使ったウェブアプリケーションを作りたくて作業していた時に起きました。
ウェブアプリが動いて、次は宅内サーバーのDB(MariaDB)へアクセスできるようにしたいと思い、S2JDBCの利用を考えました。
S2JDBCのためには、まずS2JDBC-Genでエンティティを自動生成してもらうことが必要なようです。
プロジェクトはDoltengから作ったものなのでプロジェクトエクスプローラー等の、プロジェクト直下にs2jdbc-gen-build.xmlが作成されています。これを右クリックして、「実行」→「Ant ビルド...」を選び、gen-entityのみを選択して実行すれば手順としては問題ないはずですが、そこでエラーが起きました。
環境
- OS:macOS Ventura 13.2.1(ハードはiMac 21.5-inch 2019だったり、MacBook Pro 13-inch, 2020)
- eclipse:2022-12 (4.26.0)
以下フレームワーク関連のバージョン
- struts:1.2.9
- sa-struts:1.0.4
- s2-tiger:2.4.46
- s2-framework:2.4.46
- s2-extension:2.4.46
- s2jdbc-gen:2.4.46
- freemarker:2.3.13
最初のつまずき
s2jdbc-gen-build.xmlをAntでビルドした結果のコンソールが以下。
Buildfile: /Volumes/Seagate_mac/ファイル/workspace/eclipse/wasabiapp/s2jdbc-gen-build.xml
gen-entity:
[gen-entity] Java Result: 1
BUILD FAILED
/Volumes/Seagate_mac/ファイル/workspace/eclipse/wasabiapp/s2jdbc-gen-build.xml:40: エラー: メイン・クラスを検出およびロードできませんでした
原因: java.lang.ClassNotFoundException:
対応
「S2JDBC-Gen メイン・クラスが見つからなかったかロードできません」等で調べると、以下が近そうですね。
こちらのページでは、特殊な環境向けの設定が悪さをしているとのこと。正直なところよくわかりませんが、私はmacOSなので全部UTF-8なのでは?と思い、特殊な環境向けの設定は必要ないと勝手に判断しました。
なので上記ページ通り、<jvmarg value="${vmarg.encoding}"/>
を削除することでこちらのエラーは出なくなりました。
しかし、何も書かないのもなんか不安なので、少し触っていたところ、<jvmarg value="-Dfile.encoding=UTF-8"/>
としてもエラーが出なくなったので、こちらの状態にしてあります。
<condition property="vmarg.encoding" value="-Dfile.encoding=UTF-8" else="">
<isset property="eclipse.pdebuild.home"/>
</condition>
この部分がいらなくなっちゃうので、何も書かないでもよいかなと思います。そもそもこれがなぜ上手くいかないのかはわかれば追記します。
結果
以下の対応で当該のエラーは出なくなりました。
classpathref="classpath">
- <jvmarg value="${vmarg.encoding}"/>
+ <jvmarg value="-Dfile.encoding=UTF-8"/>
</gen-entity>
2度目のつまずき
その後、s2jdbc-gen-build.xmlをAntでビルドした結果のコンソールが以下(長いのでエラーより前は途中から記載)。
...
[gen-entity] DEBUG 2023-03-09 21:11:23,177 [main] S2Containerを作成します。path=creator.dicon
[gen-entity] DEBUG 2023-03-09 21:11:23,193 [main] S2Containerを作成しました。path=creator.dicon
[gen-entity] DEBUG 2023-03-09 21:11:23,198 [main] S2Containerを作成しました。path=warmdeploy.dicon
[gen-entity] Java Result: 1
BUILD FAILED
/Users/wasabi/Documents/workspace/eclipse/wasabiapp/s2jdbc-gen-build.xml:40: Exception in thread "main" java.lang.ExceptionInInitializerError
at org.seasar.framework.util.ResourcesUtil.getResourcesTypes(ResourcesUtil.java:163)
at org.seasar.framework.convention.impl.NamingConventionImpl.addExistChecker(NamingConventionImpl.java:895)
at org.seasar.framework.convention.impl.NamingConventionImpl.addRootPackageName(NamingConventionImpl.java:428)
at org.seasar.framework.convention.impl.NamingConventionImpl.addRootPackageName(NamingConventionImpl.java:410)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.seasar.framework.util.MethodUtil.invoke(MethodUtil.java:96)
at org.seasar.framework.beans.impl.BeanDescImpl.invoke(BeanDescImpl.java:218)
at org.seasar.framework.container.assembler.AbstractMethodAssembler.invoke(AbstractMethodAssembler.java:132)
at org.seasar.framework.container.assembler.AbstractMethodAssembler.invoke(AbstractMethodAssembler.java:96)
at org.seasar.framework.container.assembler.DefaultInitMethodAssembler.assemble(DefaultInitMethodAssembler.java:49)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:69)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:48)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.init(SingletonComponentDeployer.java:76)
at org.seasar.framework.container.impl.ComponentDefImpl.init(ComponentDefImpl.java:236)
at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:563)
at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560)
at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560)
at org.seasar.framework.container.factory.S2ContainerFactory.configure(S2ContainerFactory.java:234)
at org.seasar.framework.container.factory.S2ContainerFactory.configure(S2ContainerFactory.java:211)
at org.seasar.framework.container.factory.S2ContainerFactory.<clinit>(S2ContainerFactory.java:116)
at org.seasar.framework.container.factory.SingletonS2ContainerFactory.init(SingletonS2ContainerFactory.java:152)
at org.seasar.extension.jdbc.gen.internal.util.SingletonS2ContainerFactorySupport.init(SingletonS2ContainerFactorySupport.java:61)
at org.seasar.extension.jdbc.gen.internal.command.AbstractCommand.init(AbstractCommand.java:201)
at org.seasar.extension.jdbc.gen.internal.command.AbstractCommand.execute(AbstractCommand.java:160)
at org.seasar.extension.jdbc.gen.internal.command.CommandInvokerImpl.invoke(CommandInvokerImpl.java:29)
at org.seasar.extension.jdbc.gen.command.CommandAdapter.main(CommandAdapter.java:61)
Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.findLoadedClass(java.lang.String) accessible: module java.base does not "opens java.lang" to unnamed module @29428716
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:199)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:193)
at org.seasar.framework.util.ClassLoaderUtil.getFindLoadedClassMethod(ClassLoaderUtil.java:50)
at org.seasar.framework.util.ClassLoaderUtil.<clinit>(ClassLoaderUtil.java:35)
... 29 more
Total time: 1 second
対応
出ているエラー(「java.lang.ExceptionInInitializerError」「java.lang.reflect.InaccessibleObjectException」「module java.base does not "opens java.lang" to unnamed module」)等で調べると以下のページがかなり近そうです。
引数に--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
をつけるとのこと。
さて、今回はAntでの実行ですし、javaコマンドじゃないのでどうアプローチしようかと考えました。「Ant ビルド...」を選んで、メインタブから引数を指定しても変わらず。
こちらのページにあるように、eclipse.iniに指定しても変わらず(そもそも初めから--add-opens java.base/java.lang=ALL-UNNAMED
の行がありますしね...)。
そういえば、さっきのつまずき中に、「jvmargはjvmに引数を渡している」とのような記述を見かけた気がします。
<jvmarg value="--add-opens=java.base/java.lang=ALL-UNNAMED" />
こちらを先ほどと同じところに追加してみました。すると無事、当該のエラーは出なくなりました。
結果
以下の対応で当該のエラーは出なくなりました。
classpathref="classpath">
<jvmarg value="-Dfile.encoding=UTF-8"/>
+ <jvmarg value="--add-opens=java.base/java.lang=ALL-UNNAMED" />
</gen-entity>
3度目のつまずき
その後、s2jdbc-gen-build.xmlをAntでビルドした結果のコンソールが以下。
そろそろ、私の環境が悪いだけで、入れ直したりすればいけるんじゃないかと疑います。とはいえ、好転してそうな気がするので、頑張りましょう。
...
[gen-entity] DEBUG 2023-03-10 11:02:10,690 [main] S2Containerを作成しました。path=warmdeploy.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,703 [main] S2Containerを作成します。path=s2jdbc.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,705 [main] S2Containerを作成します。path=jdbc.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,707 [main] S2Containerを作成します。path=jta.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,717 [main] S2Containerを作成しました。path=jta.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,727 [main] S2Containerを作成しました。path=jdbc.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,727 [main] S2Containerを作成します。path=s2jdbc-internal.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,729 [main] S2Containerを作成します。path=convention.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,731 [main] S2Containerを作成しました。path=convention.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,734 [main] S2Containerを作成しました。path=s2jdbc-internal.dicon
[gen-entity] DEBUG 2023-03-10 11:02:10,751 [main] S2Containerを作成しました。path=s2jdbc.dicon
[gen-entity] Java Result: 1
BUILD FAILED
/Volumes/Seagate_mac/ファイル/workspace/eclipse/wasabiapp/s2jdbc-gen-build.xml:40: Exception in thread "main" org.seasar.framework.beans.IllegalPropertyRuntimeException: [ESSR0059]クラス(org.seasar.extension.dbcp.impl.XADataSourceImpl)のプロパティ(driverClassName)の設定に失敗しました。理由はorg.seasar.framework.exception.SIllegalArgumentException: [ESSR0098]クラス(org.seasar.extension.dbcp.impl.XADataSourceImpl)[jdk.internal.loader.ClassLoaders$AppClassLoader@5ffd2b27]の型(java.lang.String)[null]のプロパティ(driverClassName)に、型(java.lang.String)[null]の値(com.mysql.jdbc.Driver)を設定できませんでした。対象のクラスは(org.seasar.extension.dbcp.impl.XADataSourceImpl)[jdk.internal.loader.ClassLoaders$AppClassLoader@5ffd2b27]です。
at org.seasar.framework.beans.impl.PropertyDescImpl.setValue(PropertyDescImpl.java:279)
at org.seasar.framework.container.assembler.AbstractBindingTypeDef.setValue(AbstractBindingTypeDef.java:321)
at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bindManual(AbstractBindingTypeDef.java:127)
at org.seasar.framework.container.assembler.AbstractBindingTypeDef.bind(AbstractBindingTypeDef.java:74)
at org.seasar.framework.container.assembler.AccessTypePropertyDef.bind(AccessTypePropertyDef.java:50)
at org.seasar.framework.container.assembler.AccessTypePropertyDef.bind(AccessTypePropertyDef.java:41)
at org.seasar.framework.container.assembler.AutoPropertyAssembler.assemble(AutoPropertyAssembler.java:56)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.assemble(SingletonComponentDeployer.java:68)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.deploy(SingletonComponentDeployer.java:48)
at org.seasar.framework.container.deployer.SingletonComponentDeployer.init(SingletonComponentDeployer.java:76)
at org.seasar.framework.container.impl.ComponentDefImpl.init(ComponentDefImpl.java:236)
at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:563)
at org.seasar.framework.container.impl.ThreadSafeS2ContainerImpl.init(ThreadSafeS2ContainerImpl.java:172)
at org.seasar.framework.container.impl.S2ContainerImpl.init(S2ContainerImpl.java:560)
at org.seasar.framework.container.impl.ThreadSafeS2ContainerImpl.init(ThreadSafeS2ContainerImpl.java:172)
at org.seasar.framework.container.factory.SingletonS2ContainerFactory.init(SingletonS2ContainerFactory.java:167)
at org.seasar.extension.jdbc.gen.internal.util.SingletonS2ContainerFactorySupport.init(SingletonS2ContainerFactorySupport.java:61)
at org.seasar.extension.jdbc.gen.internal.command.AbstractCommand.init(AbstractCommand.java:201)
at org.seasar.extension.jdbc.gen.internal.command.AbstractCommand.execute(AbstractCommand.java:160)
at org.seasar.extension.jdbc.gen.internal.command.CommandInvokerImpl.invoke(CommandInvokerImpl.java:29)
at org.seasar.extension.jdbc.gen.command.CommandAdapter.main(CommandAdapter.java:61)
Caused by: org.seasar.framework.exception.SIllegalArgumentException: [ESSR0098]クラス(org.seasar.extension.dbcp.impl.XADataSourceImpl)[jdk.internal.loader.ClassLoaders$AppClassLoader@5ffd2b27]の型(java.lang.String)[null]のプロパティ(driverClassName)に、型(java.lang.String)[null]の値(com.mysql.jdbc.Driver)を設定できませんでした。対象のクラスは(org.seasar.extension.dbcp.impl.XADataSourceImpl)[jdk.internal.loader.ClassLoaders$AppClassLoader@5ffd2b27]です。
at org.seasar.framework.beans.impl.PropertyDescImpl.setValue(PropertyDescImpl.java:258)
... 20 more
Caused by: org.seasar.framework.exception.ClassNotFoundRuntimeException: [ESSR0044]クラスが見つかりませんでした。詳細はjava.lang.ClassNotFoundException: com.mysql.jdbc.Driver
at org.seasar.framework.util.ClassUtil.forName(ClassUtil.java:100)
at org.seasar.framework.util.DriverManagerUtil.registerDriver(DriverManagerUtil.java:41)
at org.seasar.extension.dbcp.impl.XADataSourceImpl.setDriverClassName(XADataSourceImpl.java:77)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.seasar.framework.util.MethodUtil.invoke(MethodUtil.java:96)
at org.seasar.framework.beans.impl.PropertyDescImpl.setValue(PropertyDescImpl.java:251)
... 20 more
Caused by: java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at org.seasar.framework.util.ClassUtil.forName(ClassUtil.java:98)
... 28 more
Total time: 938 milliseconds
長いのでエラーより前は途中から記載ですが、エラーの前を少し多めに記載しました。
というのも、2度目のつまずきでは[gen-entity] DEBUG 2023-03-10 11:02:10,690 [main] S2Containerを作成しました。path=warmdeploy.dicon
の直後にエラーが出てましたが、今回はそのさらに後です。先ほども言いましたが、状況は好転している気がします。
対応
すいません、[jdk.internal.loader.ClassLoaders$AppClassLoader@5ffd2b27]の型(java.lang.String)[null]のプロパティ(driverClassName)に、型(java.lang.String)[null]の値(com.mysql.jdbc.Driver)を設定できませんでした。
と書いてありますね。
jdbc.diconのdriverClassName
を変更していませんでした。URL
やらuser
やらは修正していたんですけどね。
結果
環境依存になりますので、記載はしません。jdbc.dicon
を環境に合わせて修正忘れずに、ということです。
4度目のつまずき(1, 2度目のつまずきと同様)
<jvmarg value="${vmarg.encoding}"/>
を使っている他の行も、1, 2度目のつまずき同様に、以下のように修正していきます。
- <jvmarg value="${vmarg.encoding}"/>
+ <jvmarg value="-Dfile.encoding=UTF-8"/>
+ <jvmarg value="--add-opens=java.base/java.lang=ALL-UNNAMED" />
最後に
戦いの末、ようやくS2JDBC-Genが動き、エンティティを作成してもらえました!!!
そもそも、Java1.7以下であれば起きないエラーも多いので、かなり環境依存ですが、1.8以上で同様のエラーが起きた方向けに書いてます。
現状の記載内容に関してもし詳細がわかれば随時、しっかりとした原因や正しい対策など追記したいと思います。
何か、間違っているところ、詳細、原因などコメントありましたら、よろしくお願いいたします。