私は、WebSphere Portal、Spring ポートレット MVC、および Hibernate を使用することを余儀なくされているポータル プロジェクトに取り組んでいます。私は Spring も Hibernate も構成の経験があまりないので、あらゆる種類の助けをいただければ幸いです。
WebSphere 7.0.0.25 (Portal 6.1 がインストールされている) 上に JNDI 名 jdbc/eshop で JDBC データ ソースを作成しました。次に、JAAS 認証エイリアスを指定し、コンテナ管理の認証エイリアスに設定しました。テスト接続の試行は成功したので、データ ソースの構成は適切だったと思います。次のステップは、web.xml でリソース参照を作成することでした。
<resource-ref>
<description>DB Connection</description>
<res-ref-name>eshop</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
res-ref-name を ibm-web-bnd の実際の JNDI 名にバインドするために、次の行を追加しました。
<resource-ref name="eshop" binding-name="java:comp/env/jdbc/eshop" />
今私のHibernateエンティティ:
@Entity
@Table(name = "HIBERNATE_TEST", schema = "SCHEME_NAME")
public class HibernateTest implements java.io.Serializable {
private short id;
private String text;
public HibernateTest() {
}
public HibernateTest(String text) {
this.text = text;
}
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "ID")
public short getId() {
return this.id;
}
public void setId(short id) {
this.id = id;
}
@Column(name = "TEXT", nullable = false, length = 10)
public String getText() {
return this.text;
}
public void setText(String text) {
this.text = text;
}
HibernateTestDAO:
@Repository("hibernateTestDAO")
@Transactional
public class HibernateTestDAO implements GenericDAO<HibernateTest> {
@Autowired
private SessionFactory sessionFactory;
private Session sess;
public HibernateTestDAO () {
}
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sf) {
sessionFactory = sf;
}
public boolean add(HibernateTest item) {
boolean isAdded = false;
try {
sess = sessionFactory.getCurrentSession();
sess.persist(item);
isAdded = true;
} catch (Exception e) {
e.printStackTrace();
}
return isAdded;
}
public boolean edit(HibernateTest item) {
boolean isEdited = false;
try {
sess = sessionFactory.getCurrentSession();
item = (HibernateTest)sess.merge(item);
sess.update(item);
isEdited = true;
} catch (Exception e) {
e.printStackTrace();
}
return isEdited;
}
public boolean delete(HibernateTest item) {
boolean isDeleted = false;
try {
sess = sessionFactory.getCurrentSession();
item = (HibernateTest)sess.merge(item);
sess.delete(item);
isDeleted = true;
} catch (Exception e) {
e.printStackTrace();
}
return isDeleted;
}
@SuppressWarnings("unchecked")
@Override
@Transactional(readOnly = true)
public List<HibernateTest> getAll() {
List<HibernateTest> l = new ArrayList<HibernateTest>(0);
try {
sess = sessionFactory.getCurrentSession();
Query q = sess.createQuery("FROM HibernateTest");
l = (List<HibernateTest>) q.list();
} catch (Exception e) {
e.printStackTrace();
}
return l;
}
@Override
@Transactional(readOnly = true)
public HibernateTest getByID(long id) {
try {
sess = sessionFactory.getCurrentSession();
return (HibernateTest)sess.get(HibernateTest.class, new Short((short)id));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
ご覧のとおり、私はプログラム管理のトランザクションを使用したくありません。Springには、WebSphereデータソースのトランザクションを管理するためのWebSphereUowTransactionManagerクラスがあることを知りました。私はこの構成(applicationContext.xml)を試しました:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config />
<context:component-scan base-package="test.dao,test.entities,test.portlet.controller" />
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="jdbc/eshop"/>
<property name="lookupOnStartup" value="false"/>
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
<!-- Hibernate SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="annotatedClasses">
<list>
<value>test.entities.HibernateTest</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.DB2Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<!-- IBM WAS SPECIFIC -->
<prop key="hibernate.connection.datasource">jdbc/eshop</prop>
<prop key="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</prop>
<prop key="hibernate.transaction.jta.platform">org.hibernate.service.jta.platform.internal.WebSphereExtendedJtaPlatform</prop>
<!-- /END IBM WAS SPECIFIC -->
</props>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.transaction.jta.WebSphereUowTransactionManager">
<property name="userTransactionName" value="java:comp/UserTransaction" />
</bean>
<bean id="hibernateTestDAO" class="test.dao.HibernateTestDAO" />
</beans>
、しかし、それはこの例外チェーンにつながります:
エラー 500: org.springframework.beans.factory.BeanCreationException: ServletContext リソース [/WEB-INF/applicationContext.xml] で定義された名前 'transactionManager' の Bean の作成中にエラーが発生しました: init メソッドの呼び出しに失敗しました。ネストされた例外は org.springframework.transaction.TransactionSystemException: JTA UserTransaction is not available at JNDI location [java:comp/UserTransaction]; ネストされた例外は org.springframework.jndi.TypeMismatchNamingException: JNDI ロケーション [java:comp/UserTransaction] で利用可能なタイプ [class com.ibm.ws.tx.jta.UserTransactionImpl] のオブジェクトは [javax.transaction.UserTransaction] に割り当てられません
この状況での一般的な解決策は、クラスパスから jta.jar を削除することだとわかっていますが、クラスパスにこの jar がありません! IBM がベンダー固有のライブラリーを使用して UserTransaction クラスを作成する方法がわかりませんが、これを機能させる必要があるため、アプリケーションを構成するにはあなたの助けが必要です。
また、この問題を約 3 日間回避し、さまざまな構成を試しましたが、残念ながら成功しませんでした。そこで、ここで質問をする出発点として、このソースからの作業中の (著者が言ったように) 構成を使用することにしました。これを修正しようとするアイデアが尽きたので、助けが必要です。
アップデート
現在のトランザクションに関する Hibernate の不平の問題を解決できました。<tx:annotation-driven transaction-manager="transactionManager" />
指定された要素がなかったため、UOWManager はいつトランザクションを開始したいかわからなかったと思います。しかし、結局のところ、それは私の困難の終わりではありませんでした。ポートレット コントローラーのコードは次のとおりです。
public class TestDIController extends AbstractController implements ApplicationContextAware{
private ApplicationContext appCtx;
@Override
public ModelAndView handleRenderRequest(RenderRequest request,
RenderResponse response) throws Exception {
appCtx = getApplicationContext();
System.out.println(UserTransaction.class.getClassLoader());
@SuppressWarnings("rawtypes")
GenericDAO cd = (GenericDAO)appCtx.getBean("hibernateTestDAO");
ModelAndView m = new ModelAndView("test").addObject("list", cd.getAll());
return m;
}
}
ModelAndView インスタンスがそれ自体に新しいオブジェクトを追加しようとすると、HibernateTestDAO のコード行がl = (List<HibernateTest>) q.list();
次の例外をスローします。
org.hibernate.exception.SQLGrammarException: 接続を開けませんでした
...いくつかのスタックトレース...
原因: java.sql.SQLException: [jcc][t4][10205][11234][3.58.81] Null ユーザー ID はサポートされていません。ERRORCODE=-4461、SQLSTATE=42815DSRA0010E: SQL 状態 = 42815、エラー コード = -4 461
コンテナ管理の認証エイリアスを指定したため、このエラーは紛らわしいです。下の図を参照してください
ここで、「auth」は私の JAAS-J2C 認証エイリアスです。また、管理コンソールからデータ ソースへの接続をテストすると、常に成功しています。これに対する答えを探すために最善を尽くしますが、現時点では結果がありません。たとえば、ここで説明されている問題は<lookup-name>
私の場合とほとんど同じですが、web.xml で要素が定義されていないため、解決策は私には合いません。いくつかのJ2Cオプション、WebSphereのリソースアダプターを構成する必要があるかもしれません.applicationContextにいくつかの設定行が欠けている可能性があります.誰が助けてくれますか? 今回は本当に迷っています。