Easiest way to manage JPA/Hibernate transactions in swing app - swing

I have this java swing app with one thread, one database connection.
Anytime the user saves or edits something a have to write something like this:
private void buttonClickedActionPerformed(java.awt.event.ActionEvent evt) {
EntityManager em = sessionFactory.openSession();
EntityTransaction et = null;
try {
et = em.getTransaction();
et.begin();
// save, merge, update ...
et.commit();
}
catch(PersistenceException pe) {
if(et != null) et.rollback();
}
finally {
if(em != null) em.close();
}
}
I see in some tutorials references to transactions managed by the container or something like that for web apps. What about desktop? Am I missing something here? Do I really need to write all this transaction code every time?

A DAO could look like:
public class BaseDao {
protected EntityManager em;
public BaseDao() {
EntityMangerFactory emf = Persistence.createEntityMangerFactory("<your PU>");
em = emf.createEntityMangerFactory();
}
public <E> E find(Class<E> clazz, Serializable id) {
return em.find(clazz, id);
}
public <E> E getReference(Class<E> clazz, Serializable id) {
return em.getReference(clazz, id);
}
public void persist(Object entity) {
EntityTransaction transaction = em.getTransaction();
transaction.begin();
em.persist(entity);
transaction.commit();
}
... and any other methods of the EntityManager.

Related

Spring #Transactional does not rollback checked exceptions

I have been stuck for a while to make Spring rollback a transaction when a checked exception is thrown using #Transactional(rollbackFor). Here is my code:
The data access class:
#Repository
public class CustomerDao {
#Autowired
private SessionFactory sessionFactory;
public void willRollback() throws CheckedException {
sessionFactory.getCurrentSession().persist(new SpringCustomer(null, "roll back"));
throw new CheckedException();
}
}
Where CheckedException is just a simple checked exception:
public class CheckedException extends Exception {}
The service class CustomerService:
#Service
public class CustomerService {
#Autowired
private CustomerDao customerDao;
#Transactional(transactionManager = "hibernateTransactionManager", rollbackFor = CheckedException.class)
public void willRollback() throws CheckedException {
customerDao.willRollback();
}
}
Beans configurations:
#Configuration
public class BasicConfig {
#Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test_hibernate?useSSL=false");
ds.setUsername("root");
ds.setPassword("Passw0rd");
return ds;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
localSessionFactoryBean.setDataSource(dataSource());
localSessionFactoryBean.setPackagesToScan("com.home.exception.checked");
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
hibernateProperties.put("hibernate.show_sql", "true");
hibernateProperties.put("hibernate.hbm2ddl.auto", "update");
localSessionFactoryBean.setHibernateProperties(hibernateProperties);
return localSessionFactoryBean;
}
#Bean
public HibernateTransactionManager hibernateTransactionManager() {
return new HibernateTransactionManager(sessionFactory().getObject());
}
}
And finally, here is my main class:
#Configuration
#ComponentScan
#EnableTransactionManagement
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx =
new AnnotationConfigApplicationContext(Main.class);
try {
ctx.getBean(CustomerService.class).willRollback();
} catch (CheckedException e) {
e.printStackTrace();
}
ctx.close();
}
}
I've read many answers related to these questions, all of them suggesting to call the transactional method from outside the proxy itself, which I did. Regardless, the entity is always persisted in the database anyway and the transaction is not rolled back.
Any help would be appreciated.
UPDATE: As per #kavithakaran-kanapathippillai answer, I debugged the TransactionAspectSupport.completeTransactionAfterThrowing() method, and the following methods as well, and found that the rollback logic is executed. The entity still appears when querieng the db though.
So, I enabled db logging to see what queries are run, and I found the following:
2020-06-28T07:29:48.516038Z 391 Query SET autocommit=0
2020-06-28T07:29:48.520253Z 391 Query insert into spring_customer (name) values ('roll back')
2020-06-28T07:29:48.524969Z 391 Query rollback
2020-06-28T07:29:48.526026Z 391 Query SET autocommit=1
I don't know why this happens but it looks like the Spring rollback is working fine.
UPDATE2: The problem was due to my table was using the MyISAM engine (non-transactional engine). Once I changed it to InnoDB (a transactional engine), the record is not persisted anymore.
The following method is where spring checks whether to rollback when an exception is thrown. Class name is TransactionAspectSupport. You can put a break point and see whether txInfo.transactionAttribute.rollbackOn(ex) is evaluating to true
protected void completeTransactionAfterThrowing(#Nullable TransactionInfo txInfo,
Throwable ex) {
if (txInfo != null && txInfo.getTransactionStatus() != null) {
.....
if (txInfo.transactionAttribute != null &&
txInfo.transactionAttribute.rollbackOn(ex)) {
Reference:
TransactionAspectSupport.java

How to make mock JdbcTemplate.queryForObject() method

I am new for Junit and Mockito and i am not understand how to write test case for below JdbcTemplate and i tried but getting exception ,Can some one help me please
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
Code
#Repository
public class BaaisnEvcIdMSRepository {
#Autowired
private JdbcTemplate jdbcTemplate;
#Transactional
public RowMapperServerResponse getQueryEvcidRepository(BaaisnEvcIdRequest baaisnEvcIdRequest) {
RowMapperServerResponse rowMapperServerResponse = jdbcTemplate.queryForObject(
"select * from Master_Circuit WHERE master_ckt_id = ( select max(master_ckt_id) from master_circuit WHERE product = ? AND id_type = ?)",
new Object[]{baaisnEvcIdRequest.getProduct_type(),baaisnEvcIdRequest.getLata()}, new BaaisnRowMapper());
return rowMapperServerResponse;
}
}
test class
public class BaaisnEvcIdMSRepositoryTest {
#InjectMocks
BaaisnEvcIdMSRepository baaisnEvcIdMSRepository;
#Mock
JdbcTemplate jdbcTemplate;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
#Test
public void getQueryEvcidRepositoryTest() {
when(jdbcTemplate.queryForObject(eq(ArgumentMatchers.anyString()), refEq(new Object[]{ArgumentMatchers.anyInt()}), eq(String.class))).thenReturn("data");
verify(jdbcTemplate, times(1)).queryForObject(eq(ArgumentMatchers.anyString()), refEq(new Object[]{ArgumentMatchers.anyInt()}), eq(String.class));
}
}
The InvalidUseOfMatchersException is coming from your use of eq(ArgumentMatchers.anyString()) and refEq(new Object[]{ArgumentMatchers.anyInt()}). You are not supposed to wrap ArgumentMatchers inside anything else.
You also seem to aim at the wrong queryForObject method. It should be this one instead.
As mentioned before you need to call the method under test before doing the verification.
#Test
public void getQueryEvcidRepositoryTest() {
// use a real `BaaisnEvcIdRequest` object if you can
BaaisnEvcIdRequest req = Mockito.mock(BaaisnEvcIdRequest.class);
Mockito.when(req.getProduct_type()).thenReturn(1);
Mockito.when(req.getLata()).thenReturn(new Object());
Object[] array = new Object[]{req.getProduct_type(),req.getLata()};
Mockito.when(jdbcTemplate.queryForObject(Mockito.anyString(), Mockito.eq(array), Mockito.any(RowMapper.class)))
.thenReturn("data");
baaisnEvcIdMSRepository.getQueryEvcidRepository(req);
Mockito.verify(jdbcTemplate, Mockito.times(1))
.queryForObject(Mockito.anyString(), Mockito.eq(array), Mockito.any(RowMapper.class));
}

ArgumentCaptor is null

I'm trying to write a unit test for the code below where I instantiate a bean and pass it on to other private methods of the class for further processing before doing what the main method does:
public OverviewTabViewBean build(Listing listing) {
VehicleDetailListingBean vehicleDetailListingBean = new VehicleDetailListingBean();
applyVehicleDetailListingRules(listing, vehicleDetailListingBean);
OverviewTabViewBean overviewTabViewBean = new OverviewTabViewBean();
if (vehicleDetailListingBean != null) {
overviewTabViewBean.setMake(vehicleDetailListingBean.getMake());
overviewTabViewBean.setModel(vehicleDetailListingBean.getModel());
overviewTabViewBean.setAtCarId(vehicleDetailListingBean.getAtCarId());
..
}
return overviewTabViewBean;
private void applyCommonListingRules(Listing listing, VehicleDetailListingBean vehicleDetailListingBean) {
rulesEngineService.applyRules(listing, vehicleDetailListingBean, vehicleDetailRules.getCommonListingRules());
}
Test looks something like this:
#Captor
ArgumentCaptor<OverviewTabViewBean> overviewTabViewBean;
#Captor
ArgumentCaptor<VehicleDetailListingBean> vehicleDetailListingBean;
#Mock
private RulesEngineService rulesEngineService;
#Mock
private VehicleDetailRules vehicleDetailRules;
#Mock
private VehicleReferenceService vehicleReferenceService;
#BeforeMethod
public void setUp() {
MockitoAnnotations.initMocks(this);
}
/**
* build
*/
#Test
public void build() {
Listing listing = new Listing();
listing.setListingId(111L);
listing.setListingType(ListingType.NEW);
List<Rule<Listing, ListingBean>> rules1 = new ArrayList<Rule<Listing, ListingBean>>();
List<Rule<Listing, ListingBean>> rules2 = new ArrayList<Rule<Listing, ListingBean>>();
doReturn(rules1).when(vehicleDetailRules).getCommonListingRules();
doReturn(rules2).when(vehicleDetailRules).getDetailListingRules();
overviewTabViewBeanBuilder.build(listing);
verify(rulesEngineService, times(2)).applyRules(anyObject(), vehicleDetailListingBean.capture(), anyList());
.....
}
vehicleDetailListingBean is returning as null a not stepping into the if block. What am I doing wrong here?

Asp.Net MVC UNitOfWork and MySQL and Sleeping Connections

I have a MVC web app that is based on the following architecture
Asp.Net MVC2, Ninject, Fluent NHibernate, MySQL which uses a unit of work pattern.
Every connection to MySQL generates a sleep connection that can be seen as an entry in the SHOW PROCESSLIST query results.
Eventually this will spawn enough connections to exeed the app pool limit and crash the web app.
I suspect that the connections are not being disposed correctly.
If this is the case where and how should this happen?
Here is a snapshot of the code that I am using:
public class UnitOfWork : IUnitOfWork
{
private readonly ISessionFactory _sessionFactory;
private readonly ITransaction _transaction;
public ISession Session { get; private set; }
public UnitOfWork(ISessionFactory sessionFactory)
{
_sessionFactory = sessionFactory;
Session = _sessionFactory.OpenSession();
Session.FlushMode = FlushMode.Auto;
_transaction = Session.BeginTransaction(IsolationLevel.ReadCommitted);
}
public void Dispose()
{
if (Session != null)
{
if (Session.IsOpen)
{
Session.Close();
Session = null;
}
}
}
public void Commit()
{
if (!_transaction.IsActive)
{
throw new InvalidOperationException("No active transation");
}
_transaction.Commit();
Dispose();
}
public void Rollback()
{
if (_transaction.IsActive)
{
_transaction.Rollback();
}
}
}
public interface IUnitOfWork : IDisposable
{
void Commit();
void Rollback();
}
public class DataService
{
int WebsiteId = Convert.ToInt32(ConfigurationManager.AppSettings["Id"]);
private readonly IKeyedRepository<int, Page> pageRepository;
private readonly IUnitOfWork unitOfWork;
public PageService Pages { get; private set; }
public DataService(IKeyedRepository<int, Page> pageRepository,
IUnitOfWork unitOfWork)
{
this.pageRepository = pageRepository;
this.unitOfWork = unitOfWork;
Pages = new PageService(pageRepository);
}
public void Commit()
{
unitOfWork.Commit();
}
}
public class PageService
{
private readonly IKeyedRepository<int, Page> _pageRepository;
private readonly PageValidator _pageValidation;
public PageService(IKeyedRepository<int, Page> pageRepository)
{
_pageRepository = pageRepository;
_pageValidation = new PageValidator(pageRepository);
}
public IList<Page> All()
{
return _pageRepository.All().ToList();
}
public Page FindBy(int id)
{
return _pageRepository.FindBy(id);
}
}
Your post does not give any information in which scope UoW's are created.
If it is transient. It won't be disposed at all and this is up to you.
In case of InRequestScope it will be disposed after the GC has collected the HttpContext. But as I told Bob recently in the Ninject Mailing List it is possible to release all objects in the end request event handler of the HttpApplication. I'll add support for this in the next release of Ninject.
I did some investigation into the root cause of this problem. Here is a bit more information and possible solutions:
http://blog.bobcravens.com/2010/11/using-ninject-to-manage-critical-resources/
Enjoy.
Ninject makes no guarantees about when and where your IDisposables will be Disposed.
Read this post from the original Ninject man
I'd also suggest having a look around here, this has come up for various persistence mechanisms and various containers - the key thing is you need to take control and know when you're hooking in the UOW's commit/rollback/dispose semantics and not leave it to chance or cooincidence (though Convention is great).

Ehcache hangs in test

I am in the process of rewriting a bottle neck in the code of the project I am on, and in doing so I am creating a top level item that contains a self populating Ehcache. I am attempting to write a test to make sure that the basic call chain is established, but when the test executes it hands when retrieving the item from the cache.
Here are the Setup and the test, for reference mocking is being done with Mockito:
#Before
public void SetUp()
{
testCache = new Cache(getTestCacheConfiguration());
recordingFactory = new EntryCreationRecordingCache();
service = new Service<Request, Response>(testCache, recordingFactory);
}
#Test
public void retrievesResultsFromSuppliedCache()
{
ResultType resultType = mock(ResultType.class);
Response expectedResponse = mock(Response.class);
addToExpectedResults(resultType, expectedResponse);
Request request = mock(Request.class);
when(request.getResultType()).thenReturn(resultType);
assertThat(service.getResponse(request), sameInstance(expectedResponse));
assertTrue(recordingFactory.requestList.contains(request));
}
private void addToExpectedResults(ResultType resultType,
Response response) {
recordingFactory.responseMap.put(resultType, response);
}
private CacheConfiguration getTestCacheConfiguration() {
CacheConfiguration cacheConfiguration = new CacheConfiguration("TEST_CACHE", 10);
cacheConfiguration.setLoggingEnabled(false);
return cacheConfiguration;
}
private class EntryCreationRecordingCache extends ResponseFactory{
public final Map<ResultType, Response> responseMap = new ConcurrentHashMap<ResultType, Response>();
public final List<Request> requestList = new ArrayList<Request>();
#Override
protected Map<ResultType, Response> generateResponse(Request request) {
requestList.add(request);
return responseMap;
}
}
Here is the ServiceClass
public class Service<K extends Request, V extends Response> {
private Ehcache cache;
public Service(Ehcache cache, ResponseFactory factory) {
this.cache = new SelfPopulatingCache(cache, factory);
}
#SuppressWarnings("unchecked")
public V getResponse(K request)
{
ResultType resultType = request.getResultType();
Element cacheEntry = cache.get(request);
V response = null;
if(cacheEntry != null){
Map<ResultType, Response> resultTypeMap = (Map<ResultType, Response>) cacheEntry.getValue();
try{
response = (V) resultTypeMap.get(resultType);
}catch(NullPointerException e){
throw new RuntimeException("Result type not found for Result Type: " + resultType);
}catch(ClassCastException e){
throw new RuntimeException("Incorrect Response Type for Result Type: " + resultType);
}
}
return response;
}
}
And here is the ResponseFactory:
public abstract class ResponseFactory implements CacheEntryFactory{
#Override
public final Object createEntry(Object request) throws Exception {
return generateResponse((Request)request);
}
protected abstract Map<ResultType,Response> generateResponse(Request request);
}
After wrestling with it for a while, I discovered that the cache wasn't being initialized. Creating a CacheManager and adding the cache to it resolved the problem.
I also had a problem with EHCache hanging, although only in a hello-world example. Adding this to the end fixed it (the application ends normally).
CacheManager.getInstance().removeAllCaches();
https://stackoverflow.com/a/20731502/2736496