I'm building a multi-module project using Play 2.3 and Java 8. Root application and each module have a Global object. But how we know Play uses only one Global object from root application.
Simplified folder structure:
/root
/app
Global.java
/conf
application.conf
/subprojects
/user
/app
UserGlobal.java
/admin
/app
AdminGlobal.java
All Global classes placed in unnamed package.
I use such way for merging Global objects from subprojects:
1) Declared configuration variable in root application.conf
subprojects.with.globals="subprojectName1, subprojectName2, subprojectName3, ..."
2) Added private field and private method in root Global.java
private List<GlobalSettings> subprojectGlobals = new ArrayList<>();
private void LoadSubprojectGlobals(Application app)
throws ClassNotFoundException, IllegalAccessException, InstantiationException
{
String subprojectNames =
app.configuration().getString("subprojects.with.globals");
if (!subprojectNames.isEmpty())
{
Class subprojectGlobalClass = null;
for (String subprojectName : subprojectNames.split(","))
{
subprojectGlobalClass = Class.forName(
WordUtils.capitalize(subprojectName.trim().toLowerCase()) +
"Global"
);
subprojectGlobals.add(
(GlobalSettings)subprojectGlobalClass.newInstance()
);
}
}
}
3) Placed such code into onStart event handler in root Global.java
@Override
public void onStart(Application app)
{
try
{
LoadSubprojectGlobals(app);
}
catch(Exception e)
{
new RuntimeException(e);
}
for(GlobalSettings subprojectGlobal: subprojectGlobals)
{
subprojectGlobal.onStart(app);
}
}
Now if we add some new subproject we must edit subprojects.with.globals in root application.conf. And if we want to handle more global settings we need to override appropriate method in root Global.java.
It will be cool if we'll be able to determine all subproject names dynamically from java-code in root onStart. Is it possible? May be from root build.sbt or from Application object?
UPDATE
I changed my project applying @Mon Calamari's approach.
1) Removed configuration variable subprojects.with.globals from root application.conf.
2) Put all subproject Global classes into globals package:
/subprojects
/user
/app
/globals
UserGlobal.java
/admin
/app
/globals
AdminGlobal.java
3) Added configuration variable into all subproject conf files like a
application.global= globals.UserGlobal
4) Changed LoadSubprojectGlobals() implementation:
private void LoadSubprojectGlobals(Application app)
throws ClassNotFoundException, IllegalAccessException, InstantiationException
{
Reflections reflections = new Reflections("globals");
Set<Class<? extends GlobalSettings>> subprojectGlobalClasses =
reflections.getSubTypesOf(GlobalSettings.class);
for(Class subprojectGlobalClass : subprojectGlobalClasses)
{
subprojectGlobals.add(
(GlobalSettings)subprojectGlobalClass.newInstance()
);
}
}
Now if we add some new subproject we must follow some conventions about adding Global class but we have no need to keep track sub projects list.
Thanks a lot.
I am not sure how your modules/packages are arranged, but what if you use org.reflections
to get all extensions of play.GlobalSettings
class:
Reflections reflections = new Reflections("your.package");
Set<Class<? extends GlobalSettings>> classes = reflections.getSubTypesOf(GlobalSettings.class)
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