I have written (with Eclipse) a small program which uses JPA. Now I want to manualy compile and run this program using command line. I have also placed all source files in a separate directory (not within Eclipse's work space). The directory looks like:
directory
|- src
| |- javax
| | |- persistence
| | |- <...>
| |- main
| |- META-INF
| | |- javax
| | | |- persistence
| | |- persistence.xml
| |
| |- <..>
|- run.bat
Note: I purposely have 2 javax directories with all the class files in them.
run.bat contains lines:
javac -cp ./src ./src/main/Main.java
java -cp ./src main.Main
As far as I understand I am getting errors not because of the issue with the META-INF/persistence.xml file (not like many other people on stackoverflow). I am saying so because I have writen following lines in my Main:
<...>
Thread.currentThread().setContextClassLoader(new ClassLoader() {
#Override
public Enumeration<URL> getResources(String name) throws IOException {
System.out.println("resource requested=" + name);
if (name.equals("META-INF/services/javax.persistence.spi.PersistenceProvider")) {
<--- MARK ---> return Collections.enumeration(Arrays.asList(new File("src/javax/persistence/spi/PersistenceProvider.class")
.toURI().toURL()));
} else if (name.equals("META-INF/persistence.xml")) {
return Collections.enumeration(Arrays.asList(new File("src/META-INF/persistence.xml")
.toURI().toURL()));
}
return super.getResources(name);
}
});
emFactory = Persistence.createEntityManagerFactory("uzduotis");
<...>
So when I launch run.bat the program prints:
resource name=name=META-INF/services/javax.persistence.spi.PersistenceProvider
(it never gets to the part where program asks for "META-INF/persistence.xml" resource)
then it breaks and gives me an error:
If I change MARKED statement to
return super.getResources("src/" + name);
then the error says only:
What am I missing?
Peristence.xml:
EDIT:
Program prety simple: no hibernate, just a few classes which retrieve some info from REST service and work with it, mainly using javax and w3c external libraries. Photo of the project explorer to depict its simplicity.
EDIT 2. SOLUTION
I found a way to make it work although I am not entirely sure about the causes. So if anyone could answer why the following changes solved the issue I would gladly mark it as an answer
I added eclipselink and mysql-connector-java jars to the src directory. eclipselink.jar fixed the issue and mysql-connector-java.jar was needed because I got other error (I am working with database afterall). Finally I changed line in the run.bat file from
java -cp ./src main.Main
to
java -cp ./src;./src/eclipselink.jar;./src/mysql-connector-java.jar; main.Main
It seems that your application is a standard Java SE application. JPA does not work automatically, as standard Java SE environment does not contain any implementation of JPA interfaces. It seems that Eclipse adds eclipselink to the classpath under the cover, therefore your program works when you run it from within Eclipse. But when you run your program from command line, you need to add eclipselink, which is a library that contains functionality for JPA interfaces.
You may try to generate Ant build file from eclipse project, and you would see if it adds eclipselink into the classpath in build.xml file. Or even better, I recommend to turn your project into project with Maven build - you would be able to build and run your project using Maven command in the same way as Eclipse would execute it (as Eclipse uses Maven under the cover for Maven-based projects).
Edit - explanation of the role of eclipselink in JPA
Packages starting javax.persistence are mostly interfaces, annotations, they have very few classes in fact. They only define how your application communicates with underlying persistence mechanism in standard way. On the other hand, you need to include also library with implementations (classes) for the standard JPA interfaces. javax.persistence.Persistence is just a facade, which delegates all the hard work onto an implementation, which might be Eclipselink, Hibernate, or something else.
The relationship between javax.persistence and EclipseLink is similar to relationship between interfaces and classes. You may use interfaces in your code, but your application will work only if you supply interfaces with real classes at some point.
It is also possible to use Eclipselink directly and skip whole javax.persistence layer, similarly as it is possible to work with real classes directly without through interfaces. But then you need learn internal API of Eclipselink and it is not possible to change Eclipselink library for alternatives like Hibernate. Nor will you be able to reuse the knowledge of Eclipselink-specific API to a project, which uses Hibernate. Reusability of a standard API is the most important case for standardized javax.persistence interfaces.
Maybe you wonder, how the persistence API knows where it should delegate the required functionality. There are multiple hooks, how it can find out. It is possible to include path to the main implementation class in persistence.xml using provider element. Or, it simply works if you include Eclipselink into the classpath, as Eclipselink library contains special text file at standardized path, which contains required information. This special file is inside Eclipselink JAR at path META-INF/services/javax.persistence.spi.PersistenceProvider - does it ring the bell?
Related
Very simple use case, I am using Eclipse Oxygen 4.7.3a that includes support from Java 9. I have two projects that are Java 9 projects:
- projectOne
| - src
| - module-info.java
| - com
| - package1
| - first
| Classificator.java
- projectTwo
| - src
| - module-info.java
| - com
| - package2
| - second
| Classifiable.java
I want to use the Classifiable class inside the Classificator, so I try to import the second module into the first project.
module-info.java Project 1:
module projectOne {
requires projectTwo;
}
module-info.java Project 2:
module projectTwo {
}
Eclipse is giving me the error:
projectTwo cannot be resolved to a module
Do I have to gather all my Java projects under one "main project" in order to let Eclipse know that all those modules are usable inside it? Or have I missed something else?
No, you don't need them to be in the same directory. Ideally, your project-one module defines some uses, which are implements by your project-two module (or vice-versa). Get the runtime implementation of your used interfaces. For this, both jars/classes must be on the module path.
For further information on module build, multi module builds,... you can refer to this link. Even if you do not use gradle, its tutorial on java 9 module build is quite interesting and gives some insight.
While wiring as a service is certainly a viable approach (as described in the other answer), let me add that requires can be made to work, too, of course.
The thing that was probably missing from the first approach is: Eclipse still needs to know where to look for modules. In real world projects this will typically be mediated by your build tool of choice plus a plug-in like m2e or buildship.
If no such plug-in is used, a normal project dependency should be added to the Build Path of project projectOne in order to make project projectTwo visible. Once the project is on the Build Path the module defined by the project can be resolved in references in module-info.java.
I am somewhat new to RubyMine but here is my problem. I have a JRUBY Class that I want to extend from a Java class. My Java class is part of a submodule I have imported using git. This is my project structure:
src --> Submodule --> <Directories> --> ClassIWantToExtend.java
--> Ruby Code --> <Directories> --> JRubyClassThatExtendsJava.rb
However, when using RubyMine I have been unable to figure out how to extend this Java class. It can't seem to find it. My current class is blank. This is all I have:
require 'java'
class JRubyClassThatExtendsJava
end
I have tried using '<' and 'include' but when autofilling RubyMine can't seem to find my Java Class. I did just add the submodule using a CLI Git Command. Is it possible I have to add something for RubyMine to see it?
Thanks for any help in advance.
RubyMine, as far as I know (bought a license but never actually used it due this) does not include support for .java (not even a syntax highlighter) - the motivation seems to be that they have a separate product that is a Java IDE. thus this answer is not going to be RubyMine specific :
first you'll need to compile the .java sources and either pack them in a .jar or simply keep in mind what directory the .class files are (javac -d OUT_DIR)
than in your .rb you can either require 'path/to/packed.jar' or simply $CLASSPATH << 'path/to/classes/OUT_DIR'
... than you should be able to load the Java class and extend it in Ruby
I'm working on a plugin for a 3rd party software that is quite undocumented. For the plugin I'm using a external lib (.jar) managed by maven and is later on executed on a tomcat server. Everything was working great till I updated to the latest release of the library, which now is using java.util.serviceLoader in order to load a concrete implementation of a interface. When build, my project has this package structure on a tomcat server:
mypluginPackage.jar
|
---META-INF
---lib
|
--- theExternalLibUsingServiceLoader.jar
|
---META-INF
|
---services
|
--- full.path.to.TheFactoryInterface
---external.lib.path
|
--- TheFactoryInterface.class
--- TheConreteClass.class
--- mypluginCore.jar
|
---META-INF
--- my.plugin.path
|
--- MyClassUsingTheExternalLib.class
As you can see, the external library has the correct services entry which is necessary for the serviceLoader to find the concrete of a interface within META-INF. The content of the full.path.to.TheFactoryInterface file is full.path.to.TheConcreteClass, which seems legit.
My plugin (package as well as the core) however do not have any of those META-INF information.
What happens now is that every time my plugin is using a method that will trigger the serviceLoader of the external library, the serviceLoader is unable to find the concrete implementation.
What I already tried is adding the exact same services/full.path.to.TheFactoryInterface to all my META-INF directories, which is not working (I guess I would need to change the content of the full.path.to.TheFactoryInterface file but I'm not sure - because of the undocumented plugin structure for the 3rd party software - what the right (relative) path would look like).
Can anybody give me a shot what I'm doing wrong here and how to fix it so the concrete class is found by serviceLoader? What META-INF folder should the services folder with it's content be placed in and should I change the paths? Is that the error at all or am I missing something compleatly different?
I understand that this is a very special topic since the 3rd party software is unkown, but any information depending serviceLoader and it's behaviour when run across multiple jars with multiple META-INF folders and in different execution context / classpaths would be appreciated.
I was able to get it working by extending the external lib so I'm able to provide a custom ClassLoader. Turned out, the default ClassLoader was wrong.
Also I was able to get in touch with the 3rd party tool devs and get the information I needed - call it "social decompiling".
Everything working now.
I'm working on a large legacy project that I'm trying to componentize, starting with SonarQube. I'm configuring a multi-module project in sonar-project.properties. This works fine. However, I have an issue precisely identifying source folders.
Unfortunately, our modules aren't neatly separated in the file system. The project is separated into many Eclipse projects, and several Eclipse projects together form one module. I can, of course, enumerate all the projects, but this is very cumbersome as there are a lot of them. Here's a (simplified) version of our directory structure:
projects/
moduleAsubmodule1/
src/
com/mycompany/moduleA/submodule1/
moduleAsubmodule2/
src/
com/mycompany/moduleA/submodule2/
moduleBsubmodule1/
src/
com/mycompany/moduleB/submodule1/
moduleBsubmodule2/
src/
com/mycompany/moduleB/submodule2/
moduleBsubmodule3/
src/
com/mycompany/moduleB/submodule3/
Imagine many more modules and submodules, where the project name is concatenated, but the package names are nicely divided, making it much easier to differentiate on those.
moduleA.sonar.projectBaseDir=.
moduleA.sonar.sources=projects/**/src/com/mycompany/moduleA/**/*
moduleA.sonar.test=projects/**/*.test/src/com/mycompany/moduleA/**/*
According to the documentation, this should be possible for exclusions. However, I get the following error message:
16:10:44 ERROR: Unable to execute Sonar
16:10:44 ERROR: Caused by: The folder 'projects/**/src/com/mycompany/mymodule/**/*' does not exist for 'XXX:XXX:mymodule' (base directory = D:\XxxSonar\.)
So I guess globs don't work for sources? If that's indeed the case, what can I do?
We use SonarQube 4.1.2.
I had the same issue, but I solved it by doing like this:
sonar.sources=.
sonar.inclusions=projects/*/src/**/*
The inclusions/exclusions properties support wildcards. Same for your tests:
sonar.test.inclusions=projects/*/*.test/src/**/*
Wildcards are not allowed when specifying "sonar.sources". Instead, you should play with the properties that allow to narrow your source and test files. See the documentation page on how to include or exclude files to narrow the focus.
I want to replace the auto injected log object, which is of type org.apache.commons.logging.Log with an object of type org.slf4j.Logger, so that I can use it properly with Logback.
Therefore I need to create a ...Transformer class (written in Java) - that's what I got from Graeme Rocher over at the "grails-user" mailing list. I'm also aware that I have to pack this ...Transformer class within a plugin and make it a *.jar archive which I can load within the lib/ folder of the plugin. But I guess I'm doing something wrong here as I have the class, along with a META-INF folder which contains the MANIFEST.MF file as well as another folder services which holds the following file org.codehaus.groovy.transform.ASTTransformation which holds just one String: the canonical name of the ...Transformer class.
Now, if I try to do a grails clean everything is fine, BUT if I try to run grails package-plugin the console comes up with a java.lang.ClassNotFoundException.
Clipping from Stacktrace:
| Packaging Grails application...
| Error Fatal error during compilation org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Could not instantiate global transform class my.package.ast.LoggingTransformation specified at jar:file:/C:/Source/MyGrailsAST/lib/replace-logging-logback-ast.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation because of exception java.lang.ClassNotFoundException: my.package.ast.LoggingTransformation
1 error
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
Could not instantiate global transform class my.package.ast.LoggingTransformation specified at jar:file:/C:/Source/MyGrailsAST/lib/replace-logging-logback-ast.jar!/META-INF/services/org.codehaus.groovy.transform.ASTTransformation because of exception java.lang.ClassNotFoundException: my.package.ast.LoggingTransformation
Does anybody have some experience with Grails plugins which handle with AstTransformer and could give me some advice on this? Is there a good tutorial out there which I haven't seen so far?
Please let me know ;)
so, after some research, browsing and finally asking at the Grails Mailing List (see the mailing list archives at: http://grails.1312388.n4.nabble.com/Grails-user-f1312389.html I found a solution.
my goal was to create a Globals ASTTransformation, to inject a org.slf4j.Logger object instead of the usual org.apache.commons.logging.Log object into every Artefact class without annotation.
so, here are the steps:
I created Java class similar to https://github.com/grails/grails-core/blob/master/grails-logging/src/main/groovy/org/codehaus/groovy/grails/compiler/logging/LoggingTransformer.java but with my own implementation of the org.slf4j.Logger object. It is crucial that you place the Java.class under the following package: org.codehaus.groovy.grails.compiler as
Grails scans for classes that are annotated with #AstTransformer in this package. (Graeme Rocher)
and pack it into a JAR along with its MANIFEST.MF file within the META-INF/ folder. A META-INF/services directory with all its stuff is not needed as Graeme Rocher stated:
You do not need the META-INF/services stuff and I would remove it as it is probably complicating matters.
So, I guess this statement was more related to my specific problem as I only have one #AstTransformer class within my plugin, but that's just a guess. And I haven't searched for further informations on this topic. Maybe some other developer here who needs this could do some research and share his solution within this thread...
The JAR should be imported to the plugin and placed under the lib/ directory. After this you should be able to do grails clean, grails compile and grails package-plugin.
If you want to replace the log implementation, as I did, you should exclude the grails-logging and grails-plugin-log4j JARs from your designated project's classpath. This is done in the BuildConfig.groovy file:
inherits("global") {
excludes "grails-plugin-log4j", "grails-logging"
}
Now install your plugin grails install-plugin \path\to\plugin.zip and everthing should work as expected.
Hope this helps...