1

3 週間以来、私は自分が書いたいくつかのプラグインJarClassLoaderと反射を使用してロードしようとしています。
プラグインの読み込みは完璧ですが、永続性とエンティティ クラスを使用する必要がある場合、次のエラーが発生します。

GRAVE: null
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.amepa.plugin03.Test.main(Test.java:29)
Caused by: javax.persistence.PersistenceException: No Persistence provider for EntityManager named pu
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:85)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at plugin.Main.getLocalFactory(Main.java:126)
... 5 more

コマンドラインでプラグインを実行するjava -jar plugin.jar と、データベースからフェッチされたデータが完全に表示されます。また、永続化 API を使用せず、ドライバー経由で直接接続すると、反射によっても正しい結果が得られます。

エラーがどこから来たのか、可能であればそれを解決する方法を理解したいと思います。

これはプラグインのコードです:

public class Main /*implements PluginImplement*/{

    public  List<String> getStudent(){
        List<Eleves> findElevesEntities = (new ElevesJpaController(getLocalFactory())).findElevesEntities();
        List<String> lst = new ArrayList<>();
        for(Eleves el : findElevesEntities){
            lst.add(el.toString());
            System.out.println(" Eleves : "+el.toString());
        }
        return lst;
    }

    public static void main(String args[]){
        Main m = new Main();
        m.getStudent();
    }

    public static EntityManagerFactory getLocalFactory() {
        return Persistence.createEntityManagerFactory("pu");
    }
}

これは私の永続化ファイルです:

<?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="pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>entities.Eleves</class>
<properties>
  <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/emt?zeroDateTimeBehavior=convertToNull"/>
  <property name="javax.persistence.jdbc.user" value="user"/>
  <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
  <property name="javax.persistence.jdbc.password" value="password"/>
</properties>
  </persistence-unit>
</persistence>

実体

@Entity
@Table(name = "eleves")
@XmlRootElement
public class Eleves implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    private Date created;
    @Column(name = "date_bapteme")
    @Temporal(TemporalType.DATE)
    private Date dateBapteme;
    @Column(name = "date_inscription_ecole")
    @Temporal(TemporalType.DATE)
    private Date dateInscriptionEcole;
    @Column(name = "date_naissance")
    @Temporal(TemporalType.DATE)
    private Date dateNaissance;
    @Column(name = "email")
    private String email;
    @Basic(optional = false)
    @Column(name = "nom")
    private String nom;
    @Basic(optional = false)
    @Column(name = "prenom")
    private String prenom;
    @Column(name = "numero")
    private String numero;

    public Eleves() {
    }

    public Eleves(Integer id) {
        this.id = id;
    }

    public Eleves(Integer id, String nom, String prenom) {
        this.id = id;
        this.nom = nom;
        this.prenom = prenom;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Date getCreated() {
        return created;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public Date getDateBapteme() {
        return dateBapteme;
    }

    public void setDateBapteme(Date dateBapteme) {
        this.dateBapteme = dateBapteme;
    }

    public Date getDateInscriptionEcole() {
        return dateInscriptionEcole;
    }

    public void setDateInscriptionEcole(Date dateInscriptionEcole) {
        this.dateInscriptionEcole = dateInscriptionEcole;
    }

    public Date getDateNaissance() {
        return dateNaissance;
    }

    public void setDateNaissance(Date dateNaissance) {
        this.dateNaissance = dateNaissance;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getNom() {
        return nom;
    }

    public void setNom(String nom) {
        this.nom = nom;
    }

    public String getPrenom() {
        return prenom;
    }

    public void setPrenom(String prenom) {
        this.prenom = prenom;
    }

    public String getNumero() {
        return numero;
    }

    public void setNumero(String numero) {
        this.numero = numero;
    }

    @Override
    public String toString() {
        return "Eleves{" + "id=" + id + ", created=" + created + ", dateBapteme=" + dateBapteme + ", dateInscriptionEcole=" + dateInscriptionEcole + ", dateNaissance=" + dateNaissance + ", email=" + email + ", nom=" + nom + ", prenom=" + prenom + ", numero=" + numero + '}';
    }
}

そしてコントローラー:

public class ElevesJpaController implements Serializable {

    public ElevesJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }


    public List<Eleves> findElevesEntities() {
        return findElevesEntities(true, -1, -1);
    }

    public List<Eleves> findElevesEntities(int maxResults, int firstResult) {
        return findElevesEntities(false, maxResults, firstResult);
    }

    private List<Eleves> findElevesEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Eleves.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Eleves findEleves(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Eleves.class, id);
        } finally {
            em.close();
        }
    }

    public int getElevesCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Eleves> rt = cq.from(Eleves.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }    
}

それらはすべて、maven を使用して jar にパッケージ化されています。

jar をロードするメイン クラスは次のとおりです。

public class Test {
    public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException{
        JarClassLoader jcl = new JarClassLoader();
        Class loadClass = jcl.loadClass("plugin.Main");
        System.out.println(" Class : "+loadClass);
        for(Method m : loadClass.getDeclaredMethods())
            System.out.println(" Method : "+m.getName());

        Method declaredMethod = loadClass.getDeclaredMethod("getStudent");
        try {
            Object newInstance = loadClass.newInstance();
            declaredMethod.invoke(newInstance);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InvocationTargetException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

JarClassLoaderこの投稿から派生したクラスです: http://kalanir.blogspot.com/2010/01/how-to-write-custom-class-loader-to.html

上記のリンクに修正版のコードを追加します。

public class JarClassLoader extends ClassLoader {
private final String jarFile = "path_to_jar.jar"; //Path to the jar file
private Hashtable classes = new Hashtable(); //used to cache already defined classes
public JarClassLoader() {
    super(JarClassLoader.class.getClassLoader()); //calls the parent class loader's constructor
}
public Class loadClass(String className) throws ClassNotFoundException {
    return findClass(className);
}
public Class findClass(String className) {
    byte classByte[];
    Class result = null;

    result = (Class) classes.get(className); //checks in cached classes
    if (result != null) {
        return result;
    }

    try {
        return findSystemClass(className);
    } catch (Exception e) {

    }

    try {
          className = className.replaceAll("\\.", "/");
        JarFile jar = new JarFile(jarFile);
        Enumeration<JarEntry> entries = jar.entries();
        JarEntry entry = jar.getJarEntry(className + ".class");
        InputStream is = jar.getInputStream(entry);
        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
        int nextValue = is.read();
        while (-1 != nextValue) {
            byteStream.write(nextValue);
            nextValue = is.read();
        }

            classByte = byteStream.toByteArray(); 
  className = className.replaceAll("/","\\." ); 
 result = defineClass(className, classByte, 0, classByte.length,null);
         classes.put(className, result);
        return result;
    } catch (Exception e)
   { e.printStackTrace();
        return null;
    }
}

}

前もって感謝します。

4

1 に答える 1

0

JarClassLoaderリンクでコードから派生したものを使用すると、記述が不十分でバグがあります。

を使用しURLClassLoaderます。

于 2016-09-05T15:28:21.590 に答える