I have a basic ESB Fuse test project set up with the following modules:
simple-datasource
simple-model
simple-service
The datasource is configured through blueprint and the datasource attached to jndi:
<?xml version="1.0" encoding="UTF-8"?>
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
<bean id="simpleDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:#(DESCRIPTION=(LOAD_BALANCE=yes)(CONNECT_DATA=(SERVICE_NAME=xyz))(ADDRESS=(PROTOCOL=TCP)(HOST=xx.xx.xx.xx)(PORT=1521)))" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<!--bean id="simpleDataSource" class="oracle.jdbc.driver.OracleDriver">
<property name="URL" value="jdbc:oracle:thin:#(DESCRIPTION=(LOAD_BALANCE=yes)(CONNECT_DATA=(SERVICE_NAME=devd))(ADDRESS=(PROTOCOL=TCP)(HOST=10.75.192.195)(PORT=1521)))"/>
<property name="username" value="username" />
<property name="password" value="password" />
</bean-->
<service ref="simpleDataSource" interface="javax.sql.DataSource">
<service-properties>
<entry key="osgi.jndi.service.name" value="jdbc/simpleDataSource" />
</service-properties>
</service>
The model defines a persistent unit inside persistence.xml file and references the datasource through jndi (notice the long and short jndi lookup defined here, both which I have tried):
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
version="2.0">
<persistence-unit name="simple-service-persistence-unit" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<!--jta-data-source>osgi:service/javax.sql.DataSource/(osgi.jndi.service.name=jdbc/simpleDataSource)</jta-data-source-->
<jta-data-source>osgi.jndi.service.name=jdbc/simpleDataSource</jta-data-source>
<!-- list of the persistance classes -->
<class>com.model.SimpleRow</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
</persistence-unit>
The SimpleRow class uses JPA annotations:
package com.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
#Entity
#Table(name = "SIMPLE")
public class SimpleRow {
#Column(name = "simple_id")
private Long simpleId;
#Column(name = "simple_text", length =100)
private String simpleText;
public Long getSimpleId() {
return simpleId;
}
public void setSimpleId(Long simpleId) {
this.simpleId = simpleId;
}
public String getSimpleText() {
return simpleText;
}
public void setSimpleText(String simpleText) {
this.simpleText = simpleText;
}
}
I then attempt to inject the EntityManager into a service, again using blueprint and a reference to the simple-service-persistence-unit:
<?xml version="1.0" encoding="UTF-8"?>
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
http://aries.apache.org/xmlns/jpa/v1.1.0 http://aries.apache.org/schemas/jpa/jpa_110.xsd">
<bean id="simpleService" class="com.service.SimpleServiceImpl">
<jpa:context property="entityManager" unitname="simple-service-persistence-unit" />
<tx:transaction method="*" value="Required" />
</bean>
<service ref="simpleService" interface="com.service.SimpleService" />
Now when I install these modules into the fuse OSGi container the simple-datasource and simple-module both appear to install correctly. Listing these modules gives:
[ 274] [Active ] [ ] [ ] [ 60] Simple Model (1.0.0)
[ 275] [Active ] [Created ] [ ] [ 60] Simple Datasource (1.0.0)
I created a test jdbc module which used an injected DataSource and this confirmed that the DataSource is working correctly e.g.
public class DbExample {
DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void test() throws Exception {
Connection con = dataSource.getConnection();
Statement stmt = null;
DatabaseMetaData dbMeta = con.getMetaData();
....
}
Now, when I try and start the simple-service, it enters into a grace-period state and the following message is printed to the log file:
2013-07-02 11:05:33,772 | INFO | e-1.0.0-thread-1 | BlueprintContainerImpl | ? ? | 8 - org.apache.aries.blueprint.core - 1.0.1.fuse-71-047 | Bundle simple-service is waiting for dependencies [(&(&(org.apache.aries.jpa.proxy.factory=true)(osgi.unit.name=simple-service-persistence-unit))(objectClass=javax.persistence.EntityManagerFactory))]
Listing the module state shows it to be in the grace-period state:
[ 277] [Active ] [GracePeriod ] [ ] [ 60] Simple Service Bundle (1.0.0)
It eventually times out and moves into a failure state.
Now my initial thinking was that it could be a broken datasource, but the jdbc module proves that it's working fine. My subsequent thoughts are that the jndi lookup isn't working correctly, although I'm not sure how to check this. Is there any way of viewing the jndi registry? Any other suggestions welcomed.
Your bundle is waiting for a service to show up, this might either be an issue because you're referencing a service that isn't available (turn DEBUG logging on and you'll see the details in the log) or what sometimes happens (depending on the underlying version of Karaf/Aries) that you need to switch blueprint to use the synchronized deployment cause sometimes a waiting bundle doesn't catch the later started service. For doing this you need to flip the org.apache.aries.blueprint.synchronous=true in the etc/config.properties file.
Related
I need to be able to store database config properties in an external file that well be used by the application jar and include it in form of jstl expressions. (like : ${password} etc.)?
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.DB2Dialect</property>
<property name="connection.url">jdbc:db2://localhost:50001/svntools</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="connection.driver_class">com.ibm.db2.jcc.DB2Driver</property>
-->
<property name="show_sql">true</property>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.BrancheEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.RevisionEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.ProjectEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.StatistiqueEntity"/>
<mapping class="fr.gouv.education.sirhen.svnreporting.persistance.eo.DomaineEntity"/>
</session-factory>
</hibernate-configuration>
SpringConfig.xml file
<?xml version="1.0" encoding="UTF-8"?>
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<bean id="projectDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.ProjectDAOImpl">
</bean>
<bean id="reportDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.ReportDAOImpl" />
<bean id="brancheDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.BrancheDAOImpl" />
<bean id="domaineDAO" class="fr.gouv.education.sirhen.svnreporting.persistance.impl.DomaineDAOImpl" />
<bean id="svnKitDa"
class="fr.gouv.education.sirhen.svnreporting.domaine.DA.impl.SVNKitDAImpl" />
<bean id="RevisionServicesBean"
class="fr.gouv.education.sirhen.svnreporting.domaine.impl.RevisionsServicesImpl">
<property name="svnKitDa" ref="svnKitDa" />
<property name="brancheDAO" ref="brancheDAO" />
</bean>
<bean id="parser" class="fr.gouv.education.sirhen.svnreporting.transvers.utils.ParserImpl" />
<bean id="reportServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.ReportServicesImpl">
<property name="reportDAO" ref="reportDAO" />
<property name="brancheDAO" ref="brancheDAO" />
<property name="projectDAO" ref="projectDAO" />
<property name="parser" ref="parser" />
</bean>
<bean id="projectServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.ProjectServicesImpl">
<property name="projectDAO" ref="projectDAO" />
</bean>
<bean id="domaineServices"
class="fr.gouv.education.sirhen.svnreporting.service.impl.DomaineServicesImpl">
<property name="domaineDAO" ref="domaineDAO" />
</bean>
<bean id="generator"
class="fr.gouv.education.sirhen.svnreporting.domaine.generatorDocServices.impl.GeneratorDocServiceImpl" />
The class that use the session:
package fr.gouv.education.sirhen.svnreporting.persistance.impl;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import fr.gouv.education.sirhen.svnreporting.persistance.ProjectDAO;
import fr.gouv.education.sirhen.svnreporting.persistance.eo.ProjectEntity;
public class ProjectDAOImpl implements ProjectDAO {
private static final String Location_Hibernate =
"resources/hibernate.cfg.xml";
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void addProject(ProjectEntity project) {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
session.saveOrUpdate(project);
t.commit();
session.close();
}
public List<ProjectEntity> getProjects() {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
List<ProjectEntity> projects= session.createCriteria(ProjectEntity.class).list();
t.commit();
session.close();
return projects;
}
public List<String> getProjectsNames() {
File hibernatePropsFile = new File(Location_Hibernate);
Session session=new Configuration().configure(hibernatePropsFile).buildSessionFactory().openSession();
Transaction t=session.beginTransaction();
List<ProjectEntity> projects= session.createCriteria(ProjectEntity.class).list();
t.commit();
session.close();
List<String> ProjectsNames=new LinkedList<String>();
for( ProjectEntity projet : projects)
{
ProjectsNames.add(projet.getName());
}
return ProjectsNames;
}
}
An alternate approach is you can directly use hibernate.properties file instead of hibernate.cfg.xml.
But if you want to use another file then hibernate.properties file then please refer link given below:
How to read database configuration parameter using properties file in hibernate
Still, if you want to read properties file separate then you can read with normal java code to read properties file from class path or relative file path and set those properties on environment using ConfigurableEnvironment of spring.
Edited Answer
If you want to read properties file outside of your application (jar) then you can read properties file programmatically from relative file path.
I have provided one answer earlier and that was the same situation for read properties file, You can follow my Edited answer from there.
Spring Boot embedded Tomcat not loading external properties file in ApplicationListener
Now You can use System properties or Environment properties to store properties loaded earlier from relative file path and then it will available any where in the application.
#Autowired
private ConfigurableEnvironment myEnv;
or
System.setProperty ("propertyName", "propertyValue");
I am implementing the hazelcast map store for persistence. But could not autowired spring beans(DataSource below) into the hazelcast mapstore object (meaning hazelcast not getting the map store object from spring beans). I read that hazelcast supports spring DI. What am i missing ? Below is my partial map store code
If I get the bean from context using get bean like below
MySQLStore store = (MySQLStore)context.getBean(MySQLStore.class);
I get mysql store with the datasource dependency injected. So this should be an issue with Hazelcast not getting beans from spring. Am I missing any configuration in hazelcast map store.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Component;
import com.hazelcast.core.MapStore;
#Component
public class MySQLStore implements MapStore<String, ScripDetails> {
#Autowired
private DataSource dataSource;
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
#Override
public ScripDetails load(String arg0) {
System.out.println("loading data from store");
String sql = "SELECT * FROM DATA";
Connection conn = null;
Below is the spring-beans xml with has the datasource and component scan which includes the MySQLStore package.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<context:component-scan base-package="com.tlab"/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://host:port/DB" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
</beans>
Hazelcast xml below
<?xml version="1.0" encoding="UTF-8"?>
<hazelcast
xsi:schemaLocation="http://www.hazelcast.com/schema/config
http://www.hazelcast.com/schema/config/hazelcast-config-3.0.xsd"
xmlns="http://www.hazelcast.com/schema/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<network>
<join><multicast enabled="true"/></join>
</network>
<map name="scrips">
<backup-count>1</backup-count>
<time-to-live-seconds>0</time-to-live-seconds>
<max-idle-seconds>0</max-idle-seconds>
<eviction-policy>LRU</eviction-policy>
<eviction-percentage>25</eviction-percentage>
<merge-policy>hz.ADD_NEW_ENTRY</merge-policy>
<map-store enabled="true">
<class-name>com.tlab.MySQLStore</class-name>
</map-store>
</map>
</hazelcast>
In your example, Hazelcast instance is not a Spring bean. You need to configure Hazelcast instance using Spring. You can find documentation here and examples
I hope that it helps.
Thank you
I have created an example - SPRING, JPA(EclipseLink persistence provider) with JTA Transaction Manager(JBoss 7). I have observed that all the data in database is being shown in UI properly for the read operations. But when it comes to save/update or delete operation the services layer is not committing the work to database. No exception is caught(I have checked the console/log too and also debugged the code where I can see entityManager.persist/remove is being invoked without any exception).
--Code Listing--
1. Datasource configuration in standalone.xml
<datasource jta="true" jndi-name="java:/mysql_customerdb3" pool-name="mysql_customerdb3_pool" enabled="true" use-java-context="true" use-ccm="true">
<connection-url>jdbc:mysql://localhost:3306/customerdb</connection-url>
<driver>mysql</driver>
<security>
<user-name>root</user-name>
<password>root</password>
</security>
<statement>
<prepared-statement-cache-size>10</prepared-statement-cache-size>
<share-prepared-statements>true</share-prepared-statements>
</statement>
</datasource>
<drivers>
<driver name="mysql" module="com.mysql">
<driver-class>com.mysql.jdbc.Driver</driver-class>
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
</driver>
<driver name="h2" module="com.h2database.h2">
<xa-datasource-class>org.h2.jdbcx.JdbcDataSource</xa-datasource-class>
</driver>
</drivers>
Database driver configuration in module.xml
persistence.xml
org.eclipse.persistence.jpa.PersistenceProvider
java:/mysql_customerdb3
com.springforbeginners.model.Customer
customerdispatcher-servlet.xml
<context:annotation-config />
<context:component-scan base-package="com.springforbeginners" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" >
<property name="loadTimeWeaver" ref="loadTimeWeaver" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
</bean>
<bean id="loadTimeWeaver" class="org.springframework.instrument.classloading.SimpleLoadTimeWeaver" >
</bean>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManagerName" value="java:jboss/TransactionManager"/>
<property name="userTransactionName" value="java:jboss/UserTransaction"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />
CustomerServiceImpl.java
package com.springforbeginners.service;
import com.springforbeginners.dao.CustomerDAO;
import com.springforbeginners.model.Customer;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
#Service
public class CustomerServiceImpl implements CustomerService {
#Autowired
private CustomerDAO customerDAO;
#Transactional
#Override
public void addCustomer(Customer customer) {
customerDAO.addCustomer(customer);
}
#Transactional
#Override
public List<Customer> listCustomer() {
return customerDAO.listCustomer();
}
#Transactional
#Override
public void removeCustomer(Integer customerId) {
customerDAO.removeCustomer(customerId);
}
}
CustomerDAOImpl.java
package com.springforbeginners.dao;
import com.springforbeginners.model.Customer;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.stereotype.Repository;
#Repository
public class CustomerDAOImpl implements CustomerDAO {
#PersistenceContext(unitName="CustomerDetailsPU3")
private EntityManager entityManager;
#Override
public void addCustomer(Customer customer) {
entityManager.persist(customer);
}
#Override
public List<Customer> listCustomer() {
return entityManager.createQuery("select c from Customer c", Customer.class).getResultList();
}
#Override
public void removeCustomer(Integer customerId) {
Customer customer = (Customer) entityManager.getReference(Customer.class, customerId);
if (null != customer) {
entityManager.remove(customer);
}
}
}
I do not know what and where exactly is something missing. But with the above code the read operations are working as expected. Problem is with save operations. I have converted the above example to use non-JTA datasource(also modified standalone.xml for jta=false) and to use JpaTransactionManager as below
With non-JTA datasource and 'org.springframework.orm.jpa.JpaTransactionManager' all operations(read as well as save/update/delete) are working fine.
But the JTA version of my example is not working as expected(save operations not committing work to database). Any help/pointers appreciated.
Thanks
Prakash
James,
I will be running this application on JBoss. But one datasource on JBoss and other on Glassfish and transaction should span save operation on both datasources simultaneously. This is what I am trying to achieve. I have a web application including spring for service(data) layer currently running on JBoss.
As you said earlier - I will have two persistence.xmls one for JBoss and one for Glassfish. As I am doing this first time I was/am in doubt whether the transaction(that spans two datasources on different servers-in this case JBoss and Glassfish), can this be executed entirely by JBoss(in case if the entire business logic resides in serviceImpl class deployed on JBoss)? In this case I will be using JBoss transaction manager( property name="transactionManagerName" value="java:jboss/TransactionManager" ). Is this sufficient or do I need to similarly have Glassfish transaction manager too? Sorry if this has created the confusion.
Another question from me was that is there a provision for speifying jndi ports in persistence.xml/anywhere else?(Definitely I will have two different persistence.xmls and I will mention the target server as JBoss in one and as Glassfish in another).
Do we have a technique in spring by which business logic can be distributed across different servers like JBoss/Glassfish and still under one single transatcion? I did not know if this can be an option. Were u talking about this scenario in which it will require two different deployment scripts one for each server?
Thanks
Prakash
What is your persistence.xml?
Since you are using JTA, you must define the "eclipselink.target-server"="JBoss"
My persistence.xml(modified) now looks like below. Added target server property in persistence.xml. This solved the problem.
<persistence-unit name="CustomerDetailsPU3" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>java:/mysql_customerdb3</jta-data-source>
<class>com.springforbeginners.model.Customer</class>
<properties>
<property name="eclipselink.target-server" value="JBoss" />
</properties>
</persistence-unit>
Thanks
Prakash
I'm using JP2 in my current web project. My main database holds the main entities. To connect on this DB i defined a Persitence Unit with a JTA Datasource:
Persistance.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="MyPU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>MyDB</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.logging.logger" value="ServerLogger"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
and the JTA Datasource defined in sun-resources.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="org.postgresql.ds.PGSimpleDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="post-gre-sql_mydb_mypool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="5432"/>
<property name="databaseName" value="mydb"/>
<property name="User" value="myuser"/>
<property name="Password" value="mypass"/>
<property name="URL" value="jdbc:postgresql://localhost:5432/mydb"/>
<property name="driverClass" value="org.postgresql.Driver"/>
<property name="characterEncoding" value="UTF-8" />
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="MyDB" object-type="user" pool-name="post-gre-sql_mydb_mypoll"/>
</resources>
And this is how i access the database on my DAO classes (witch are #ManagedBeans and #SessionScoped):
#ManagedBean(name = "pageDao")
#SessionScoped
public class PageDao implements Serializable {
#Resource
private UserTransaction utx = null;
#PersistenceUnit(unitName = "MyPU")
private EntityManagerFactory emf = null;
public EntityManager getEntityManager() {
return emf.createEntityManager();
}
public List<PageEnt> getAll() { ... }
public PageEnt getOne(long pageId) { ... }
public void addPage(PageEnt newPage) throws RollbackFailureException, PreexistingEntityException, Exception { ... }
public PageEnt update(PageEnt page) throws RollbackFailureException, NonexistentEntityException, Exception { ... }
public void remove(PageEnt page) throws RollbackFailureException, Exception { ... }
}
One of entities (customer) has properties for connecting on a separate (per-customer) database, witch are defined in run-time. These properties includes:
Databse name
Host and port
User and Password
My question are:
How do I efficiently create a database connection in run-time?
How can I create a new EntityManager from container-managed resources if there is no per-customer PersistanceUnit and Datasources defined (witch are defined at deploy-time)?
If i have to manually deal with the EntityManagerFactory (witch, as i learned in college, is a heavy and expansive object), how do I efficiently do that? Is there a good-practice or pattern?
How would the DAO pattern work? How do my DAO class will get the EntityManager?
Big thanks from Brazil.
It is possible to switch between multiple data sources at run time. It is provided by Spring AbstractRoutingDataSource . It is required to override the #determineCurrentLookupKey() method which will return a key to decide the specific datasource that is needed to be connected. Also there should be spring configuration that maps each of the possible keys and the corresponding data sources that are to be connected. Some thing like
<jee:jndi-lookup id="DataSource_Client1" jndi-name="DataSource_Client1" />
<jee:jndi-lookup id="DataSource_Client2" jndi-name="DataSource_Client" />
<bean id="DynamicDataSource" class="concrete implementation class name of AbstractRoutingDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="Client1" value-ref="DataSource_Client1" />
<entry key="Client2" value-ref="DataSource_Client2" />
</map>
</property>
</bean>
A possible reference to this Dynamic DataSource
Hope this answers one of your questions
*when i deploy project in glassfish entitymanager is null.if i use another thing instead of RPC like servlet project work probably *
session bean is:
#Stateless
public class logic implements logicLocal {
#PersistenceContext(unitName="T2PU")
private EntityManager em;
#Override
public void addToDB(Test t){
em.persist(t);
}
}
and GWT RPC is :
public class MainRPCImpl extends RemoteServiceServlet implements MainRPC {
#EJB
logicLocal logic;
#Override
public String addToDB(Test t) {
String m="fail";
try {
logic.addToDB(t);
m="done successfuly";
} catch (Exception e) {
return m;
}
return m;
}
}
persistence unit is :
<persistence-unit name="T2PU" transaction-type="JTA">
<jta-data-source>acm</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
and glassfish-resources
<resources>
<jdbc-connection-pool allow-non-component-callers="false" associate-with-thread="false" connection-creation-retry-attempts="0" connection-creation-retry-interval-in-seconds="10" connection-leak-reclaim="false" connection-leak-timeout-in-seconds="0" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" fail-all-connections="false" idle-timeout-in-seconds="300" is-connection-validation-required="false" is-isolation-level-guaranteed="true" lazy-connection-association="false" lazy-connection-enlistment="false" match-connections="false" max-connection-usage-count="0" max-pool-size="32" max-wait-time-in-millis="60000" name="mysql_acm_rootPool" non-transactional-connections="false" pool-resize-quantity="2" res-type="javax.sql.DataSource" statement-timeout-in-seconds="-1" steady-pool-size="8" validate-atmost-once-period-in-seconds="0" wrap-jdbc-objects="false">
<property name="serverName" value="localhost"/>
<property name="portNumber" value="3306"/>
<property name="databaseName" value="acm"/>
<property name="User" value="root"/>
<property name="Password" value="1234"/>
<property name="URL" value="jdbc:mysql://localhost:3306/acm"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" jndi-name="acm" object-type="user" pool-name="mysql_acm_rootPool"/>
</resources>
specially thanks in advance.
Maybe there are different reasons, but don't you need to use the jdbc context prefix for your JNDI name in persistence.xml? Something like this:
<jta-data-source>jdbc/acm</jta-data-source>
From the Glassfish administration guide:
A JDBC resource is created by specifying the connection pool with
which the resource will be associated . Use a unique Java Naming and
Directory Interface (JNDI) name to identify the resource. ... Because
all JNDI names are in the java:comp/env subcontext, when specifying
the JNDI name of a JDBC resource in the Administration Console, use
only the jdbc/name format.