.
requires. E.g. if your module contains a method which is public available and returns a type of another module. When transitive is not used, any module reading your module, would explicitly have to add the dependent module.
- requires static <module name>: this is an optional dependency. The module is needed at compile time, but not at run time.
exports
The exports directive indicates which public types of the module’s package are accessible to other modules. We used this directive in the previous posts where the package com.mydeveloperplanet.jpmshi was made accessible in order that module com.mydeveloperplanet.jpmshello was able to use the HiModules class.
exports com.mydeveloperplanet.jpmshi;
Also an exports…to directive exists. After the to keyword, it is possible to set the list of packages which are allowed to use the exported packages.
opens
The opens directive also indicates which public types of the module’s package are accessible to other modules. The difference with exports is that opens is not during compile time but only during run time, while exports is during compile time and during run time. package com.mydeveloperplanet.jpmsopens in module com.mydeveloperplanet.jpmshi. The contents is similar to that of the HiModules class:
public class OpensModules { public String getHiOpens() { return "Hi Opens Directive!"; } }); } }
Build with Maven and run module com.mydeveloperplanet.jpmshi. The build was successful because we did not explicitly use class OpenModules. We only used it within our reflection code and thus the compiler had no information that the class was being used during run time.
We add the following to the module-info of module com.mydeveloperplanet.jpmshi:
opens com.mydeveloperplanet.jpmsopens;
Build with Maven and run the example again, the output is:
Hello Modules! The XML namespace prefix is: xml Hi Modules! Hi Modules! Hi Opens Directive!
Now that we added the open directive to the module-info, it is allowed to use the class during run time.
It is also possible to set the open directive in front of the module, this way all public types within the module can be used during run time. continue reading this paragraph, it is a good thing to revise the concept of services. I can recommend the following articles:
Create the Service Provider Interface
We first will create the Service Provider Interface by means of the following steps:
- We into package com.mydeveloperplanet.serviceproviderinterface. We create the service as a singleton and provide it with one method printServiceNames. This method loads the service implementations package com.mydeveloperplanet.serviceprovider1 with class ServiceProvider1.
Before we are able to do this, we need to adapt the module-info of module com.mydeveloperplanet.serviceproviderinterface in order to export the package which module com.mydeveloperplanet.serviceproviderinterface as a Maven dependency to the pom which will use the created service. We will extend the HelloModules with a checkProvidesWith method. But first, we need to add to module-info.java of com.mydeveloperplanet.serviceprovider1 the provides…with directive. to module-info of com.mydeveloperplanet.serviceproviderinterface the uses directive. output as expected.
Add second Service Provider
To conclude with, we add a second Service Provider ServiceProvider2 identical the module directives were explained and used in several examples. This concludes this series of Java 9 Modules. I hope you enjoyed this series and start using Java 9 Modules!
2 thoughts on “Java 9 Modules directives (part 3)”
good stuff, though I’m left with a question. I’m writing “Spring” (or any framework that does classpath scanning for classes annotated with annotation, JPA/CDI, etc). How does my framework read my later developed library? is this the service provider stuff? could you show an example of this?
For my next post, I created a small Spring Boot application with one RestController. I only had to add Spring modules into my module-info. I did not have to ‘export’ or ‘open’ anything in this case. Spring does use reflection in some cases. When you encounter an IllegalAccessException, you will need to use the ‘opens’ directive as described above: Spring is not allowed to use your classes during compile time, but is allowed to use them during runtime (for those that are marked with the ‘opens’ directive).
You only need to use the service provider stuff if you are going to use the Java Services. When you are using Spring, you do not need to use this.