2010-12-07 5 views
7

Ich verwende MATLAB R2007b, Java 1.6 SE, Eclipse Helios und MySql 5 unter Windows XP Pro SP3.Java JPA-Klasse für MATLAB

Ich versuche, eine Klassenbibliothek zu erstellen, die JPA-Anmerkungen verwendet, um auf eine MySql 5-Datenbank zuzugreifen. Die Idee ist, dass das MATLAB-Skript diese Java-Objekte instanziiert, die eine API für den Zugriff auf die DB bereitstellen.

Ich kann meine annotierten Klassen erstellen, die innerhalb von Eclipse arbeiten (d. H. JUnit-Test). Ich kann den Code in ein Jar exportieren, das ich von einer Eingabeaufforderung ausführen kann.

Ich aktualisiere den MATLAB Java-Klassenpfad mit javaaddpath(). Ich kann meine Klasse in MATLAB instanziieren. Aber wenn ich meine init() aufrufen, die Anrufe javax.persistence.Persistence.createEntityManagerFactory(), erhalte ich die gefürchtete

"No Persistence Provider für EntityManager"

Dieser Fehler bedeutet in der Regel, dass die Datei persistence.xml ist nicht am richtigen Ort. Aber es muss sein, weil mein Jar von der Kommandozeile aus funktioniert. Das Hinzufügen des META-INF-Ordners zum MATLAB-Java-Klassenpfad hilft nicht. Es wird auch weder das JAR-Objekt extrahiert noch die extrahierte Ordnerstruktur dem Klassenpfad hinzugefügt, unabhängig davon, ob META-INF hinzugefügt wurde oder nicht.

Hat jemand irgendwelche Ideen, nussig oder nicht? Hat jemand dies jemals in irgendeiner Version von MATLAB getan.

Danke.

-Reilly.

+0

Haben Sie einen Persistenzanbieter auf dem Klassenpfad? – willcodejavaforfood

+0

Überlegen Sie, Matlab zu aktualisieren. R2007b ist alt und seine eingebettete JVM ist Java 1.5. Es verursacht dieses Problem wahrscheinlich nicht, aber es könnte Ihre andere Entwicklung reibungsloser machen. –

+0

Versuch 2010a. Gleicher Fehler. – Reilly

Antwort

0

Sind Sie absolut sicher, dass Sie den Namen der Persistenzeinheit im Aufruf richtig geschrieben haben:

javax.persistence.Persistence.createEntityManagerFactory(String puName) 

, die auch Sie den gleichen Fehler geben würde. Der Name unterscheidet zwischen Groß- und Kleinschreibung.

+0

Ja. Der Name der Persistenzeinheit ist in meiner Java-Klasse fest codiert, daher wird derselbe Wert übergeben, egal ob ich in der Befehlszeile von MATLAB oder von Java aus laufe. – Reilly

2

Stellen Sie sicher, dass auf Ihrem Klassenpfad ein JPA-Provider-Jar (z. B. eclipselink.jar) vorhanden ist.

+0

+1 Dies ist ein guter Kandidat. Matlab verwaltet seinen eigenen Java-Klassenpfad, also ist es nicht unbedingt der gleiche wie der Befehl "java" in der Befehlszeile. Ab R2010b wird Matlab nicht mit javax.persistence geliefert, daher müssen Sie eine JAR dafür und JAR mit Ihren eigenen Klassen bereitstellen. –

+0

Ja. Hier ist, was ich auf meinem MATLAB Classpath haben: – Reilly

+0

antlr-2.7.6.jar com.barronassociates.auspex.rotorcraft.jar commons-Sammlungen-3.1.jar dom4j.jar ejb3-persistence.jar hibernate3.jar hibernate- annotations.jar hibernate- commons annotations.jar hibernate-core.jar hibernate- entitymanager.jar javassist.jar jta.jar mysql-connector-java-5.1.7-bin.jar slf4j- api-1.5.6.jar slf4j-simple-1.5.6.jar – Reilly

8

Nun, ich fand "eine Antwort". Irgendwo bevor ich einen Beitrag über den Unterschied in den "dynamischen" und "statischen" MATLAB-CPs gesehen habe. Das "statische" cp ist eine Textdatei, die beim Start geladen wird. Das "dynamische" cp wird zur Laufzeit geladen und Sie manipulieren es normalerweise mit M-Skriptaufrufen. Das habe ich versucht.

Also habe ich meine Gläser zum dynamischen Pfad hinzugefügt und es hat nicht funktioniert.

Ich habe sie am Ende des statischen Pfades hinzugefügt und bekam verschiedene Fehler, die mit dem XML-Parsing zusammenhängen. Fortschritt!

Dann habe ich meine Gläser am Anfang des statischen Pfades hinzugefügt und es funktioniert.

Um Bart Simpson zu zitieren: Craptackular.

Vielen Dank für Ihre Ideen. Fragen Sie mich eine C# -Frage, damit ich reziprokieren kann ...

-reilly.

+0

+1 für "craptacular" –

+3

Sinnvoll - der statische Klassenpfad entspricht dem System class Entlader; Der dynamische Klassenpfad wird mit einem benutzerdefinierten Matlab URLClassLoader ausgeführt. APIs wie JAX-WS, die Klassen vivifizieren müssen, können zu Problemen führen, da die API-Klassen im statischen Klassenpfad Klassendefinitionen, die in den dynamischen Klassenpfad geladen werden, nicht "sehen" können. JPA hatte wahrscheinlich das gleiche Problem. Wenn Sie den statischen Klassenpfad ändern, können Sie eine benutzerdefinierte classpath.txt in dem Verzeichnis verwenden, in dem Sie Matlab starten, anstatt classpath.txt in der Matlab-Installation selbst zu bearbeiten. leichtere Wartung. –

+1

Danke, Andrew. Ich wusste nichts über meine eigene classpath.txt. Das kümmert sich um meine Hauptbeschwerde zu diesem Thema. – Reilly

8

Während der Arbeit mit Java in MATLAB stieß ich häufig auf Probleme mit dem dynamischen Klassenpfad. Zur Umgehung des Problems wurde mit der Verwendung von classpath.txt jedes Problem gelöst.

Der Umgang mit verschiedenen Umgebungen, z. B. Test und Produktion, führt zu mehreren classpath.txt Dateien in Ihrem MATLAB-Startverzeichnis. Die Verwendung verschiedener MATLAB-Versionen fügt der Anzahl der classpath.txt Dateien einen weiteren Multiplikator hinzu.

ClassPathHacker.java ist eine Option dynamisch Klassen und JAR-Dateien auf Ihre statischen Classpath hinzufügen. Mit diesem Ansatz müssen Sie nicht mehr auf classpath.txt tippen. Ihre Java-Klassenpfadkonfiguration kann am vorgesehenen Ort bleiben startup.m.

+0

+1 Das sieht sehr nützlich aus! Meine Matlab App hat tatsächlich diese Nenvironments x nmatlabversions verschiedene Startup-Verzeichnisse mit diesen benutzerdefinierten Dateien; das könnte die Dinge wirklich vereinfachen. –

3

Dies ist nur eine Fortsetzung Ihrer Antwort über statische vs dynamische Klassenpfade. Hier ist eine Funktion, mit der Sie diagnostizieren können, wo eine Java-Klasse aus Matlab geladen wird, und ob es eine Maskierung der Klassendefinitionen gibt. Sie könnten andere Kollisionen sehen; zumindest dom4j.jar und commons-collections.jar werden mit Matlab ausgeliefert, aber ich weiß nicht, welche Versionen.

function whereisjavaclassloadingfrom(ClassName) 
%WHEREISJAVACLASSLOADINGFROM Show where a Java class is loaded from 
% 
% whereisjavaclassloadingfrom(ClassName) 
% 
% Shows where a Java class is loaded from in this Matlab session's JVM. 
% This is for diagnosing Java class load problems, such as classpath 
% ordering issues, seeing if a class of a given name is included in an 
% unexpected JAR file, etc. 
% 
% Displays output to console. 
% 
% Examples: 
% 
% whereisjavaclassloadingfrom('java.util.HashMap') 
% whereisjavaclassloadingfrom('com.ldhenergy.etools.MxUtil') 
% whereisjavaclassloadingfrom('com.google.common.collect.Maps') 
% whereisjavaclassloadingfrom('org.apache.commons.math.complex.Complex') 

% Use javaArray to get Class object without having to instantiate. This 
% lets it work with objects that have private or non-zero-arg constructors, 
% and avoids side effects of object construction. 
% (Would use java.lang.Class.forName(), because that's a more direct way of 
% doing this, but it doesn't work for stuff on the dynamic classpath.) 
ja = javaArray(ClassName,1); 
klass = ja.getClass().getComponentType(); 

klassLoader = klass.getClassLoader(); 
if isempty(klassLoader) 
    % JVM used null to represent the "bootstrap" class loader 
    % I think that's the same as the "system" class loader 
    klassLoader = java.lang.ClassLoader.getSystemClassLoader(); 
end 
klassLoaderStr = char(klassLoader.toString()); 

klassFilePath = [strrep(ClassName, '.', '/') '.class']; 
try 
    % This logic assumes that the classes exist as files in the class 
    % loader. It's a valid assumption for mainstream class loaders, 
    % including the one's I've seen with Matlab. 
    klassUrl = klassLoader.getResource(klassFilePath); 
    if isempty(klassUrl) 
     klassUrlStr = ''; 
    else 
     klassUrlStr = char(klassUrl.toString()); 
    end 
catch err 
    klassUrlStr = sprintf('ERROR: %s', err.message); 
end 

% Get all locations, to reveal masked definitions 
urls = enumeration2array(klassLoader.getResources(klassFilePath)); 

disp(sprintf('Version: %s\nClass:  %s\nClassLoader: %s\nURL:   %s', version,... 
    char(klass.getName()), klassLoaderStr, klassUrlStr)); 
if numel(urls) > 1 
    disp('Class is masked:'); 
    for i = 1:numel(urls) 
     disp(sprintf('URL %d:  %s', i, char(urls(i)))); 
    end 
end 

%% 
function out = enumeration2array(jenum) 
tmp = {}; 
while jenum.hasMoreElements() 
    tmp{end+1} = jenum.nextElement(); 
end 
out = [tmp{:}];