0
是的,我知道我應該使用Declarative Services
或Blueprint
但是我想弄清楚一個簡單的例子,使用較低級別的API來獲得OSGi的感覺。OSGi與JPA:雖然代碼似乎沒有啓動服務
我只想知道代碼有什麼問題,爲什麼我無法啓動服務?!!
我用兩種方法這裏:一個ServiceTracker
,另一個爲ServiceReference
,我知道都是可靠但可能有人plz幫助我出去找此示例代碼工作。會非常感謝這!
這裏是我的代碼:
我有一個簡單賬戶實體類:
package model.account;
import javax.persistence.*;
@Entity
public class Account {
@Id @GeneratedValue
int id;
double balance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Account{" + "id=" + id + ", balance=" + balance + '}';
}
}
的AccountClient爲:
package client;
public class AccountClient {
public void run(EntityManagerFactory emf) {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Account a = new Account();
a.setBalance(100.0);
em.persist(a);
em.getTransaction().commit();
TypedQuery<Account> q = em.createQuery("SELECT a FROM Account a", Account.class);
List<Account> results = q.getResultList();
System.out.println("\n*** Account Report ***");
for (Account acct : results) {
System.out.println("Account: " + acct);
}
em.close();
}
}
的persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" 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">
<persistence-unit name="Accounts" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>model.account.Account</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="eclipselink.target-database" value="Derby"/>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/accountDB;create=true"/>
<property name="javax.persistence.jdbc.user" value="app"/>
<property name="javax.persistence.jdbc.password" value="app"/>
<property name="eclipselink.logging.level" value="FINE"/>
<property name="eclipselink.logging.timestamp" value="false"/>
<property name="eclipselink.logging.thread" value="false"/>
<property name="eclipselink.logging.exceptions" value="true"/>
<property name="eclipselink.orm.throw.exceptions" value="true"/>
<property name="eclipselink.jdbc.read-connections.min" value="1"/>
<property name="eclipselink.jdbc.write-connections.min" value="1"/>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
<property name="eclipselink.weaving" value="true"/>
</properties>
最後的激活與ServiceReference
爲:
package client;
public class Activator implements BundleActivator {
BundleContext ctx;
ServiceReference[] serviceReferences;
EntityManagerFactory emf;
public void start(BundleContext context) throws Exception {
ctx = context;
System.out.println("Gemini JPA Basic Sample started");
try{
serviceReferences = context.getServiceReferences(
EntityManagerFactory.class.getName(),
"(osgi.unit.name=Accounts)");
}catch(Exception e){
e.printStackTrace();
}
if(serviceReferences != null){
emf = (EntityManagerFactory)context.getService(serviceReferences[0]);
}
if(emf != null){
new AccountClient().run(emf);
}
}
public void stop(BundleContext context) throws Exception {
if(serviceReferences != null){
context.ungetService(serviceReferences[0]);
}
System.out.println("Gemini JPA Basic Sample stopped");
}
}
ServiceTracker
:
package client;
public class Activator implements BundleActivator, ServiceTrackerCustomizer {
BundleContext ctx;
ServiceTracker emfTracker;
public void start(BundleContext context) throws Exception {
ctx = context;
System.out.println("Gemini JPA Basic Sample started");
/* We are in the same bundle as the persistence unit so the services should be
* available when we start up (if nothing bad happened) and the tracker is really
* just saving us the lookup, but this is the idea of how you would listen for a
* persistence unit coming from another bundle.
*/
emfTracker = new ServiceTracker(ctx, EntityManagerFactory.class.getName(), this);
emfTracker.open();
System.out.println("Started finally!!");
}
public void stop(BundleContext context) throws Exception {
emfTracker.close();
System.out.println("Gemini JPA Basic Sample stopped");
}
/*========================*/
/* ServiceTracker methods */
/*========================*/
public Object addingService(ServiceReference ref) {
System.out.println("reached in add");
Bundle b = ref.getBundle();
System.out.println("Got ref");
Object service = b.getBundleContext().getService(ref);
System.out.println("service");
String unitName = (String)ref.getProperty(EntityManagerFactoryBuilder.JPA_UNIT_NAME);
System.out.println("search");
if (unitName.equals("Accounts")) {
new AccountClient().run((EntityManagerFactory)service);
System.out.println("Found and started");
}
return service;
}
public void modifiedService(ServiceReference ref, Object service) {}
public void removedService(ServiceReference ref, Object service) {}
}
是的,我也做了同樣的方式。我嘗試了另一種方法,它將實例化EntityManagerFactory的對象並調用Persistence.createEntityManagerFactory(「Accounts」);它會給出「沒有找到名稱帳戶的持久性單元」的錯誤。你有什麼意見嗎? – Amrit
Persistence.createEntityManagerFactory(「Accounts」)執行類路徑掃描,不會在OSGi環境中工作。 – sebplorenz
雙子座JPA使用Extender模式來查找您的persistence.xml文件。因此,JPA擴展程序將等待清單中包含Meta-Persistence標頭的包。如果它找到一個,它將使用這個bundle上下文來查找這個bundle中的persistence.xml文件。 persistence.xml文件然後由Gemini JPA讀取,實體使用持久bunlde上下文加載。然後將配置的EntityManagerFactory作爲服務添加到上下文中。如果這不起作用,那麼可能是您的持久性包或JPA擴展程序未啓動,Meta-Persistence丟失... – sebplorenz