0

I am having a Java EE application that uses JPA as a persistence framework having transaction type JTA. I am using EntityManager annotated with PersistenceContext. My SessionBean looks like this:

package com.session;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.ejb.LocalBean;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import com.beans.Bean_B;

/**
 * Session Bean implementation class Bean_BSession
 */
@Stateless
@LocalBean
public class Bean_BSession implements Bean_BSessionLocal {

    @PersistenceContext(unitName = "bench")
    private EntityManager em;


    /**
     * Default constructor.
     */
    public Bean_BSession() {
    }

    @Override
    public List<Bean_B> findAll(int A_Id) {
        // TODO Auto-generated method stub
        List<Bean_B> bList = null;
            Query q = em
                    .createQuery("Select b FROM Bean_B b where b.BI_AID = :id");
            q.setParameter("id", A_Id);

            bList = (List<Bean_B>) q.getResultList();

        return bList;
    }

    @Override
    public int delete(int BI_ID) {
        // TODO Auto-generated method stub
            Query q = em
                    .createQuery("delete from Bean_B b where b.BI_ID = :id");
            q.setParameter("id", BI_ID);

        return q.executeUpdate();
    }
}

When I put it on a test of multiple user I don't find it scaling though I am having max-pol size of the datasource 200. My Persistence.xml looks like:

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
                        http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
    version="2.1">

    <persistence-unit name="bench">

        <jta-data-source>jdbc/benchDS</jta-data-source>

        <class>com.beans.Bean_A</class>
        <class>com.beans.bean_B</class>
        <class>com.beans.Bean_C</class>
        <class>com.beans.Bean_D</class>
        <exclude-unlisted-classes>false</exclude-unlisted-classes>
        <properties>

        </properties>
    </persistence-unit>
</persistence>

Let me know what are the changes I need to incorporate. Thanks in advance!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Can you clarify your post on how you figured out it's not scaling enough & multiple user means exactly what happens, are you creating concurrent requests & how many. What is there in logs, if processing is stuck at some point. – Nayan Wadekar Jul 23 '15 at 10:50
  • Yes, I am creating concurrent request by putting it under load test. I found number of request/sec (throughput) to be very low. Log does not have any problem. It is all fine. – MUKUND KUMAR Jul 23 '15 at 11:35
  • I'm not sure, but might the HQL delete be using a table-level lock? If so, you'll likely get better scalability if you use `remove()`. – hugh Jul 23 '15 at 12:11
  • @hugh May be..I can try with that. But can you please confirm that, the way I have created the EntityManager object and I am using it, is correct? – MUKUND KUMAR Jul 23 '15 at 12:24
  • I don't see any problem with how you're getting the `EntityManager`, and `findAll` looks sensible. I'd suggest that if you just want to execute HQL, rather than using the ORM features and dealing in Java objects, you're not getting much benefit from JPA and Hibernate. I'd consider switching from an `EntityManager` to just using a `Datasource`, but of course that depends on what else you're planning to do with this. – hugh Jul 23 '15 at 12:31
  • @hugh I tried by replacing the delete statement with em.remove, but no success. I just want to know if I concurrently access this EntityManager instance for doing delete operation, then how It is going to behave? And wanted to know whether I need to close the entitymanager explicitly?? – MUKUND KUMAR Jul 23 '15 at 12:51
  • No success as in you get the same performance characteristics? EJB is all designed to be multithreaded and scalable, so it shouldn't have any trouble. You shouldn't need to close your EntityManager - it's dependency injected, so its lifecycle is the container's responsibility. If you do, it should throw an IllegalStateException: http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#close-- – hugh Jul 23 '15 at 13:20
  • 1
    One of the most common reasons for Hibernate/JPA based applications not scaling is poor or naive query construction resulting in the infamous "N+1 SELECT" problem. – Steve C Jul 24 '15 at 00:55
  • @hugh Yes no success as in performance. I observed one thing, by concurrently accessing the methods findAll() and delete(), I found that the same reference of em(EntityManager) is being used for each request to the function. So, can it be the reason for this to not scale at higher concurrency level, given the fact that same entitymanager reference is used so the threads will wait to get a hold on it? – MUKUND KUMAR Jul 24 '15 at 05:53
  • What kind of object is the session bean injected into and called from? – Steve C Jul 24 '15 at 12:50
  • @Mukund - The entitymanager is container managed, and will be based on the vendor's performance optimisations. If it's shared, it's because the container expects that to be more efficient. The JEE infrastructure is designed for performance and scalability, so the entitymanager should be very efficient (although the detail of its optimisation will be vendor-specific). The container would not reuse the reference if it couldn't handle concurrent calls. – hugh Jul 25 '15 at 11:25
  • Mukund, "J2EE" died when "Java EE" was introduced May 2006. I edited your question accordingly. And @hugh, please carefully read https://java.net/projects/javaee-spec/pages/JEE – BalusC Jul 26 '15 at 06:50
  • Noted, thank you Balus. (Don't think I can edit my comment to correct that) – hugh Jul 28 '15 at 06:33

0 Answers0