i have application consists of wars, core ejb lots of service beans in jar , remote interfaces in jar. packaged in ear , running on glassfish 4.1.
now want add extenstion points or plugin support core ejb.
the objective have different hot-pluggable data import services share same interface because fetch , normalize financial data vendors reuters , bloomberg.
these plugins should detected , managed "plugin manager" bean in core ejb jar. plugins should support load, undload , replace @ runtime.
ideally plugin interfaces in separate package, else can develop against them without need application or glassfish , without java ee stack. want deploy plugins on demand , not whole application.
currently try use cdi instance iterator works fine 2 import service implementations, long in core ejb. if put 1 implementation separate ejb jar, not found cdi. guess problem glassfish loads each ejb jar application in separate classloader.
now comes current simplified code!
the plugin interface in separate jar package:
package com.photon.extensions; import java.io.serializable; public interface importserviceextension extends serializable { string getimportservicename(); }
the plugin implementation in separate ejb jar package not found:
package com.photon.services.extensions.vitrex.services; import com.photon.extensions.importserviceextension; import javax.ejb.remote; import javax.ejb.stateless; @remote(importserviceextension.class) @stateless public class reutersimportservice implements importserviceextension { @override public string getimportservicename() { return "reuters"; } }
the plugin implementation in core ejb jar package found:
package com.photon.services.extensions; import com.photon.extensions.importserviceextension; import javax.ejb.stateless; @stateless public class bloombergimportservice implements importserviceextension { @override public string getimportservicename() { return "bloomberg"; } }
the remote interface "plugin manager" in remote interfaces jar:
package com.photon.services.extensions; import java.util.list; import javax.ejb.remote; @remote public interface importserviceextensionsremote { list<string> getimportservicenames(); }
the "plugin manager" bean implementation in core ejb jar:
package com.photon.services.extensions; import com.photon.extensions.importserviceextension; import java.util.arraylist; import java.util.iterator; import java.util.list; import javax.ejb.stateless; import javax.enterprise.inject.instance; import javax.inject.inject; @stateless public class importersservice implements importserviceextensionsremote { @inject private instance<importserviceextension> importserviceextensions; @override public list<string> getimportservicenames() { iterator<importserviceextension> iter = importserviceextensions.iterator(); list<string> names = new arraylist<>(); while ( iter.hasnext() ) { importserviceextension extension = iter.next(); names.add(extension.getimportservicename()); } return names; } }
and controller renders names website in wars:
package com.photon.website; import com.photon.services.extensions.importserviceextensionsremote; import javax.ejb.ejb; import javax.enterprise.context.requestscoped; import javax.inject.named; @requestscoped @named public class importcontroller implements serializable { @ejb private importserviceextensionsremote importserviceextensions; public string getimportservicenames() { string names = ""; ( string name : importserviceextensions.getimportservicenames() ) { names += name; } return names; } }
in end "bloomberg" rendered.
now questions:
am on right track?
if so, missing in code?
are there better solutions problem (osgi, custom clazz.forname, ...)?
i cannot give complete answer, here food thoughts...
i guess problem glassfish loads each ejb jar application in separate classloader.
you nailed it. sadly per jee spec, it's expected behaviour.
i don't know glassfish there might feature allowing share classloader between deployments (there in wildfly - called deployment isolation). might resolve problem.
other thing know wildfly can have application deployed server module have access other deployments (and class loaders). if there similar in glassfish, try that. in case willing give shot wildfly, here link issue discussed.
now, from cdi point of view behaviour correct , afraid there no way change it, because not have access class loader other deployments (if had, might load beanmanager
given deployment , search relevant bean).
i hope gives @ least insight.
Comments
Post a Comment