Forum Stats

  • 3,769,395 Users
  • 2,252,961 Discussions
  • 7,875,018 Comments

Discussions

Getting a datasource from a persistence-unit

mmillman
mmillman Member Posts: 113
edited Sep 30, 2008 6:40PM in TopLink/JPA
Is there any way to get the name of the datasource (non-jta or jta) from a persistence unit via the EntityManagerFactory or EntityManager instances?

We need to do some JDBC work (for exotic data types) and are currently parsing the persistence.xml file ourselves to get the data source name (which is an awful thing to do) but would much rather be able to say
Connection conn = Utility.getConnection(EntityManger em)
or even
String datasource = Utility.getDataSource(EntityManager em)
.

Thanks, Mark
Tagged:

Answers

  • obrienmi8
    obrienmi8 Member Posts: 160
    Mark,
    Hi, you could try the following code that I verified on an SE JPA app.

    UnitOfWorkImpl uow = (UnitOfWorkImpl)((JpaEntityManager)entityManager).getActiveSession().acquireUnitOfWork();
    Connection conn = uow.getAccessor().getConnection();
    System.out.println("EntityManager: " + entityManager + " Connection: " + conn);

    Logs:
    ------------------
    EL Config]: 2008.09.29 12:23:26.805--ServerSession(25120699)--Connection(25530565)--Thread(Thread[main,5,main])--Connected: jdbc:oracle:thin:@y.y.y.y:1521:orcl
    User: S----
    Database: Oracle Version: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
    With the Partitioning, OLAP and Data Mining options
    Driver: Oracle JDBC driver Version: 11.1.0.0.0-Beta5
    [EL Finest]: 2008.09.29 12:23:28.336--ServerSession(25120699)--Thread(Thread[main,5,main])--End deploying Persistence Unit stat jpa oracle; state Deployed; factoryCount 1
    [EL Finer]: 2008.09.29 12:23:31.008--ServerSession(25120699)--Thread(Thread[main,5,main])--client acquired
    [EL Finer]: 2008.09.29 12:23:39.946--UnitOfWork(4929007)--Thread(Thread[main,5,main])--acquire unit of work: 2551763
    EntityManager: [email protected] Connection: [email protected]

    from the EclipseLink User Group post...
    http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg00518.html

    thank you
    /[email protected]
  • mmillman
    mmillman Member Posts: 113
    Thanks but this does not seem to work in J2EE. I tried the following and it always gets the Accessor but acc.getConnection() always returns null.
      public static Connection getConnection(EntityManager em) {
        Connection conn = null;
        if (em != null && em.isOpen()) {
            Session ss = null;
            int test = 0; // change this in the debugger to test options
            switch (test){
            case 0:
              ss = ((EntityManagerImpl)em).getServerSession().getActiveSession();
              break;
            case 1:
              ss = ((EntityManagerImpl)em).getActiveSession();
              break;
            case 2:
              ss = ((EntityManagerImpl)em).getSession();
              break;
            case 3:
              ss = ((JpaEntityManager)em).getServerSession().getActiveSession();
              break;
            case 4:
              ss = ((JpaEntityManager)em).getActiveSession();
              break;
            case 5:
              ss = ((JpaEntityManager)em).getSession();
              break;
            }
            if ( ss != null ){ 
              UnitOfWorkImpl uow = (UnitOfWorkImpl)ss.acquireUnitOfWork();
              if (uow != null ){
                Accessor acc = uow.getAccessor();
                if ( acc != null ){
                  conn = acc.getConnection();
                }
              }
            }
        }
        return conn;
      }
  • obrienmi8
    obrienmi8 Member Posts: 160
    Mark,
    Hi, Here is the container-mode version of the code running on Oracle WebLogic 10.3 where the EntityManager is a local stateless session bean on a servlet client.


    ((JNDIConnector)((DatabaseLogin)((UnitOfWorkImpl)((JpaEntityManager)entityManager.getDelegate()).getActiveSession().acquireUnitOfWork()).getProject().getDatasourceLogin()).getConnector()).getDataSource()

    using....


    persistence.xml
    <jta-data-source>oracle10RemoteDS</jta-data-source>

    @Local @Stateless
    public class ApplicationService implements ApplicationServiceLocal {
    @PersistenceContext(unitName="unified",type=PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

    public Object insert(Object class1) {
    Object returnObject = null;
    UnitOfWorkImpl uow = null;
    EntityManagerImpl entityManagerDelegate = null;
    DatabaseLogin databaseLogin = null;
    JNDIConnector connector = null;
    DataSource dataSource = null;

    try {
    // Container mode
    entityManagerDelegate = (EntityManagerImpl)entityManager.getDelegate();
    uow = (UnitOfWorkImpl)((JpaEntityManager)entityManagerDelegate).getActiveSession().acquireUnitOfWork();
    databaseLogin = (DatabaseLogin)uow.getProject().getDatasourceLogin();
    connector = (JNDIConnector)databaseLogin.getConnector();
    dataSource = connector.getDataSource();
    System.out.println("dataSource: " + dataSource);



    // SE mode
    //UnitOfWorkImpl uow = (UnitOfWorkImpl)((JpaEntityManager)entityManager).getActiveSession().acquireUnitOfWork();
    //accessor = uow.getAccessor();
    // RESOURCE_LOCAL will be null in a when JTA is used
    //Connection conn = accessor.getConnection();
    //System.out.println("EntityManager: " + entityManager + " Connection: " + conn);
    .....

    LOGS:
    [EL Finer|http://forums.oracle.com/forums/]: 2008.09.30 11:57:00.899--ServerSession(1432988)--Thread(Thread[)--client acquired
    [EL Finer|http://forums.oracle.com/forums/]: 2008.09.30 11:57:00.899--UnitOfWork(17480442)--Thread(Thread[)--TX binding to tx mgr, status=STATUS_ACTIVE
    [EL Finer|http://forums.oracle.com/forums/]: 2008.09.30 11:57:00.899--UnitOfWork(17480442)--Thread(Thread[)--acquire unit of work: 18439304
    dataSource: [email protected]




    STACKTRACE
    uow UnitOfWorkImpl (id=11793)
    project Project (id=11812)
    datasourceLogin DatabaseLogin (id=11818)
    connector JNDIConnector (id=11829)
    dataSource RmiDataSource (id=11493)
    driverClass "weblogic.jdbc.jta.DataSource" (id=11518)
    driverUrl "jdbc:weblogic:jta:oracle10RemoteDS" (id=11540)
    jtaRegistrationName "oracle10RemoteDS" (id=11543)
    poolName "oracle10RemoteDS" (id=11543)
    scope "Global" (id=11545)
    txDataSource true
    useDriver true

    There could be 2 other ways of getting both the jta and nonJta datasources using WebLogic specific code - but the fields holding the PersistenceUnitInfoImpl and EntityManagerFactory that point to the RmiDataSource are protected with no get() public accessor - so not available.

    1)
    entityManagerDelegate EntityManagerImpl (id=11498)
    factory EntityManagerFactoryImpl (id=11505)
    setupImpl EntityManagerSetupImpl (id=11510)
    persistenceUnitInfo PersistenceUnitInfoImpl (id=11479)
    jtaDataSource RmiDataSource (id=11493)
    driverUrl "jdbc:weblogic:jta:oracle10RemoteDS" (id=11540)

    2)
    this ApplicationService_5ptwty_Impl (id=11092)
    entityManager $Proxy82 (id=11158)
    h TransactionalEntityManagerProxyImpl (id=11164)
    persistenceUnit PersistenceUnitInfoImpl (id=11170)
    jtaDataSource RmiDataSource (id=11189)
    driverUrl "jdbc:weblogic:jta:oracle10RemoteDS" (id=11198)

    thank you
    [email protected]
  • mmillman
    mmillman Member Posts: 113
    Still no go -- BUT I'm using a non-jta-datasource and I'm running in OC4J so either of those might responsible for the failure. Thanks for your great suggestions though. They are much appreciated. Mark
      public static Connection getConnection(EntityManager em) {
        Connection conn = null;
        if (em != null && em.isOpen()) {
          JpaEntityManager jem = (JpaEntityManager)em.getDelegate();
          if (jem != null) {
            Session session = jem.getActiveSession();
            if (session != null) {
              UnitOfWorkImpl uow = (UnitOfWorkImpl)session.acquireUnitOfWork();
              if (uow != null) {
                Accessor acc = uow.getAccessor();
                if (acc != null) {
                  conn = acc.getConnection(); // STILL ALWAYS RETURNS NULL
                }
              }
            }
          }
        }
        return conn;
      }
  • obrienmi8
    obrienmi8 Member Posts: 160
    Mark,

    Hi, I tried non-JTA code on OC4J.
    Try the following change acc.getDatasourceConnection() - tested on OC4J 10.1.3.4 using a RESOURCE_LOCAL non-JTA connection to Oracle 10g entityManager on a servlet.
    I get the same [email protected] connection to my Oracle 10 db from either the .getConnection() or .getDatasouceConnection() call - verify your persistence.xml properties

    <property name="eclipselink.target-server" value="OC4J"/>
    <property name="eclipselink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="eclipselink.jdbc.platform" value="org.eclipse.persistence.platform.database.oracle.OraclePlatform"/>


    if (acc != null) {
    //conn = acc.getConnection(); // returns null (I get the same T4CConnection)
    conn = (Connection)acc.getDatasourceConnection(); // returns oracle.jdbc.driver.T4CConnection
    }

    [EL Finer]: 2008.09.30 17:03:07.905--ServerSession(24691161)--Thread(Thread[HTTPThreadGroup-1,9,HTTPThreadGroup])--client acquired
    [EL Finer]: 2008.09.30 17:03:13.061--UnitOfWork(18699935)--Thread(Thread[HTTPThreadGroup-1,9,HTTPThreadGroup])--acquire unit of work: 11546616
    08/09/30 17:03:20 __Connection: [email protected]


    I suspect you are running a RESOURCE_LOCAL entitymanager on your servlet client (not on an EJB) that defines all database properties like 3) below.
    like
    public class FrontController extends HttpServlet implements Servlet {
    public EntityManagerFactory emf = Persistence.createEntityManagerFactory("unified");
    public EntityManager entityManager = emf.createEntityManager();

    not
    @Local @Stateless
    public class ApplicationService implements ApplicationServiceLocal {
    @PersistenceContext(unitName=&quot;unified",type=PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;

    1) JTA on OC4J - NOPE
    Debugging in to UnitOfWorkImpl - I see the [email protected]
    However, I think this is still a tx datasource because usesExternalTransactionController = true
    uow UnitOfWorkImpl (id=534)
    project Project (id=573)
    datasourceLogin DatabaseLogin (id=582)
    connector JNDIConnector (id=592)
    dataSource ManagedDataSource (id=599)
    m_connectionManger OracleConnectionManager (id=613)
    m_connectionRetryInterval 1
    m_dataSourceName "OracleDS" (id=619)
    m_debug ManagedDataSourceDebugInfo (id=620)
    m_dmsConnectionStatMap WeakHashMap<K,V> (id=622)
    m_loginTimeout 0
    m_logWriter null
    m_managedConnectionFactory ManagedConnectionFactoryImpl (id=624)
    m_manageLocalTransactions true
    m_manageSqlObjects "basic" (id=626)
    m_maxConnectAttempts 3
    m_mBean ManagedJDBCDataSource (id=632)
    m_password null
    m_reference null
    m_unStattedConnections WeakHashMap<K,V> (id=698)
    m_unStattedConnectionsLock Object[0] (id=658)
    m_url null
    m_user null
    usesExternalTransactionController true

    Using your getConnection(EntityManager em) code:

    acc DatabaseAccessor (id=537)
    datasourceConnection null

    using:
    <persistence-unit name="unified" transaction-type="JTA">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <non-jta-data-source>jdbc/OracleDS</non-jta-data-source>
    <properties>
    <property name="eclipselink.target-server" value="OC4J"/>


    2) non-JTA on OC4J - NOPE
    using..
    entityManager.getTransaction().begin(); // non-JTA
    System.out.println("__Connection: " + getConnection(entityManager));
    on..

    <persistence-unit name="unified" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <non-jta-data-source>jdbc/OracleDS</non-jta-data-source>

    does not work with...
    @PersistenceContext(unitName=&quot;unified",type=PersistenceContextType.TRANSACTION)
    private EntityManager entityManager;


    08/09/30 16:45:59 Exception: Cannot use resource level transactions with a container managed EntityManager

    3) non-JTA, non container managed on OC4J - YES
    using..


    // Local non-JTA application managed EMF and EM
    public EntityManagerFactory emf = Persistence.createEntityManagerFactory("unified");
    public EntityManager entityManager = emf.createEntityManager();

    persistence.xml
    <persistence-unit name="unified" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <properties>
    <property name="eclipselink.target-server" value="OC4J"/>
    <property name="eclipselink.logging.level" value="FINEST"/>
    <property name="eclipselink.session-name" value="eclipselinkwls"/>
    <property name="eclipselink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="eclipselink.jdbc.platform" value="org.eclipse.persistence.platform.database.oracle.OraclePlatform"/>
    <property name="eclipselink.jdbc.url" value="jdbc:oracle:thin:@x.x.x.x:1521:orcl"/>
    <property name="eclipselink.jdbc.user" value="scott"/>
    <property name="eclipselink.jdbc.password" value="password...."/>


    uow UnitOfWorkImpl (id=518)
    platform Oracle10Platform (id=544)
    project Project (id=527)
    aliasDescriptors null
    datasourceLogin DatabaseLogin (id=533)
    cacheTransactionIsolation 5
    connectionHealthValidatedOnError true
    connector DefaultConnector (id=542)
    connectDirectly true
    databaseURL "jdbc:oracle:thin:@10.156.53.19:1521:orcl" (id=555)
    driver OracleDriver (id=556)
    driverClass Class<T> (oracle.jdbc.driver.OracleDriver) (id=557)
    driverClassName "oracle.jdbc.driver.OracleDriver" (id=558)
    driverURLHeader "" (id=560)


    [email protected]
    acc DatabaseAccessor (id=571)
    activeBatchWritingMechanism ParameterizedSQLBatchWritingMechanism (id=575)
    datasourceConnection T4CConnection (id=579)
    database "x.x.x.x:1521:orcl" (id=638)
    databaseMetaData OracleDatabaseMetaData (id=639)
    databaseProductVersion "Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production\nWith the Partitioning, OLAP and Data Mining options" (id=641)
    thinVsessionProgram "JDBC Thin Client" (id=736)
    thinVsessionTerminal "unknown" (id=737)
    timeout null
    timestamptzInGmt true
    txnLevel 2
    txnMode 0
    url "jdbc:oracle:thin:@x.x.x.x:1521:orcl" (id=738)
    useFetchSizeWithLongColumn false
    userName "SCOTT" (id=739)
    usingXA false
    ver T4C7Oversion (id=740)
    versionNumber 10201
    walletLocation null
    whichDMS 2
    wrapper null
    xaWantsError false


    With the following change...
    public Connection getConnection(EntityManager em) {
    Connection conn = null;
    if (em != null && em.isOpen()) {
    JpaEntityManager jem = (JpaEntityManager)em.getDelegate();
    if (jem != null) {
    Session session = jem.getActiveSession();
    if (session != null) {
    UnitOfWorkImpl uow = (UnitOfWorkImpl)session.acquireUnitOfWork();
    if (uow != null) {
    Accessor acc = uow.getAccessor();
    if (acc != null) {
    //conn = acc.getConnection(); // returns null (I get the same T4CConnection)
    conn = (Connection)acc.getDatasourceConnection(); // returns oracle.jdbc.driver.T4CConnection
    }
    }
    }
    }
    }
    return conn;
    }

    we get...

    [EL Finer]: 2008.09.30 17:03:07.905--ServerSession(24691161)--Thread(Thread[HTTPThreadGroup-1,9,HTTPThreadGroup])--client acquired
    [EL Finer]: 2008.09.30 17:03:13.061--UnitOfWork(18699935)--Thread(Thread[HTTPThreadGroup-1,9,HTTPThreadGroup])--acquire unit of work: 11546616
    08/09/30 17:03:20 __Connection: [email protected]

    thank you
    [email protected]
  • mmillman
    mmillman Member Posts: 113
    Still no go -- and we are using a LOCAL_RESOURCE EntityManager BUT we're also still using the Toplink Jar delivered with JDev P4, not yet the Ecliselink jar. We were waiting for the next release of JDev to make that move. SO ... that may be why we're getting different results.

    Thanks for all you help. Mark
This discussion has been closed.