I'm working on a Java project in Eclipse, which is built using Maven. I'm using some recycled code from an older project, and one of these classes looks for a file in the META-INF/services
folder of the JAR with a particular name, then parses the text of this file. In this particular example, it looks for a file with the name of a Java interface, then grabs the class name of the implementation from inside the file.
So basically what I'm trying to do is include a file in the "META-INF/services" folder of the JAR with a file name (X), and one line of text (Y). I'm guessing this should be done using Maven, maybe by specifying an attribute in the POM file, but my research hasn't turned up anything. I know you're not supposed to hard-code or manually type out any META files, so I'm not sure what to do here.
In src/main/resources , simply create a META-INF folder and place your files here. In this way, you could find them in the META-INF folder of the built JAR. Besides, you should remove the <resource> element you added in the pom.
The META-INF directory, if it exists, is used to store package and extension configuration data, including security, versioning, extension and services.
It shouldn't be at the project root, but directly under the source folder. At runtime, the persistence. xml file is searched in the classpath, under META-INF. So if you want the META-INF folder to be put at the top of the compiled package tree, you need to put it at the top of the source tree.
Create a new source folder with the location src/main/resources
, then create your META-INF/services
folder in there and drop in your fully-qualified class name (FQCN) file. This should copy them into the jar file automatically. So for implementations of an interface with a FQCN of com.acme.MyInterface
, you'll have:
Project | src | | main | | java | | [your source code] | | resources | | META-INF | | services | | com.acme.MyInterface
Note that com.acme.MyInterface
is the name of the file, not a directory structure like a Java package. The name of the file is the FQCN of the interface that you're implementing, and in it, you'll have the FQCN of each implementation on its own line, e.g.:
com.example.MyInterfaceImpl com.example.AnotherMyInterfaceImpl
It's worth noting that this applies to Gradle projects with the default source sets as well.
Once you do this, you can load all the implementations of the interface using ServiceLoader
:
ServiceLoader<MyInterface> loader = ServiceLoader.load(MyInterface.class); for (MyInterface service : loader) { // Prints com.example.MyInterfaceImpl and com.example.AnotherMyInterfaceImpl System.out.println(service.class.getName()); }
Some things to note:
ServiceLoader.load
If these conditions won't work for you, then you may want to switch to another system, e.g. a CDI-style framework like Spring, EJB, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With