В нашем проекте мы пытаемся получить код, который в настоящее время развернут в WebSphere, работающий над Liberty.
После получения сообщения MDB вызывает метод в службе, который вставляет данные в базу данных DB2. .
Проблема в том, что при вызове flu sh мы получаем следующие ошибки в журнале:
javax.persistence.TransactionRequiredException: no transaction is in progress
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.checkTransactionNeeded(AbstractEntityManagerImpl.java:1136) ~[hibernate-entitymanager-5.1.3.Final.jar:5.1.3.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:1297) ~[hibernate-entitymanager-5.1.3.Final.jar:5.1.3.Final]
[ERROR ] WLTC0017E: Resources rolled back due to setRollbackOnly() being called.
Других ошибок нет, например, SQL запрос не выполняется. правильно или что-то в этом роде.
Поскольку этот код отлично работает в WebSphere, мне интересно, что-то не так в конфигурации или Liberty делает что-то другое при обработке транзакций.
Ниже соответствующие фрагменты кода и конфигурации:
@Service
public class IdentificationService implements IIdentificationService {
@Autowired
private IIdentificationDAO identificationDAO;
@Transactional
public Identification insertIdentificationData(RequestForIdentificationRequest request, String referenceNumber) {
final Identification identification = new Identification();
...
identificationDAO.create(identification);
LOGGER.debug("Identification record saved with id: {}", identification.getId());
return identification;
}
}
@Repository
public class IdentificationDAO extends BaseDAO implements IIdentificationDAO {
@Override
public void create(final Identification identification) {
insertRecord(identification);
}
}
public abstract class BaseDAO
{
@PersistenceContext(name = "UserData", unitName = "UserData")
private EntityManager em;
/**
* @param record
*/
public <T> void insertRecord(final T record)
{
em.persist(record);
em.flush();
}
}
public class Identification implements Serializable {
@Id
@Column(name = "ID")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(sequenceName = "IDENTIFICATION_SEQ", name = "sequenceGenerator", allocationSize = 1)
private Long id;
...
}
applicationContext. xml
<jee:jndi-lookup id="userDataSource" jndi-name="jdbc/userdataDB" />
<bean id="userDataEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="UserData" />
<property name="persistenceXmlLocation" value="classpath:persistence-userdata.xml" />
<property name="dataSource" ref="userDataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="false" />
<property name="databasePlatform" value="org.hibernate.dialect.DB2Dialect" />
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="userDataEntityManagerFactory" />
</bean>
server. xml
<library id="DB2JCCLib">
<fileset dir="/etc/liberty/jdbc" includes="db2jcc4.jar, db2jcc_license_cisuz.jar, db2jcc_license_cu.jar"/>
</library>
<dataSource id="UserDB" jndiName="jdbc/userdataDB" type="javax.sql.XADataSource"
isolationLevel="TRANSACTION_READ_COMMITTED">
<jdbcDriver libraryRef="DB2JCCLib" javax.sql.XADataSource="com.ibm.db2.jcc.DB2XADataSource"/>
<properties.db2.jcc serverName="${datasource.userdb.serverName}" portNumber="${datasource.userdb.portNumber}"
databaseName="${datasource.userdb.databaseName}"
user="user" password="password"/>
</dataSource>
ОБНОВЛЕНИЕ : Проблема оказалась в нескольких bean-компонентах диспетчера транзакций (названных одинаково) в конфигурации, указывающих на разные базы данных. Назначение им уникальных имен и явная ссылка на них в аннотации транзакций помогли