New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OSGi : RouteRegistryInitializer which is responsible for servlet initialization logic is not invoked in OSGi #4376
Comments
It looks like this is a question of the web server bundle which is used in OSGi container. |
Another thing to mention is jetty websocket implementation which uses |
I don't know whether this is a common issue with OSGi containers and web server bundles but The first one doesn't care about
As a result : if you use As a result in my specific case I have a jar bundle which register In the result jetty boot make servlet initialization with Servlet context based on I made a hack which grabs this unused servlet context ( Only this way makes the bundle work with Flow: routes are registered correctly and client resources are available. I don't know whether this is an issue which we have to solve on our side somehow to make it work properly with OSGi containers. |
Hi Denis, I asked for the So what I would try in your case is to write a This would look like this: @Component
public class OSGiRouteRegistryInitializer {
private final List<Component> routes= new CopyOnWriteArrayList<>();
@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC)
void addRoute(Component foo) {
routes.add();
// do something else with foo
}
void removeRoute(Component foo) {
routes.remove(foo);
// do something else with foo
}
} whereas all @routes are OSGi components like this @Component(service=Component.class)
@Route("")
public class MyRoute extends Div {
public HelloWorld() {
setText("Hello world");
}
} Maybe this could work if it is possible to add/remove Routes dynamically to/from the RouteRegistry which might relate to #3913 . Maybe then for each Route one would have to use another Maybe thos hints help you to realize the OSGi support in Vaadin 11. Kind regards, |
Thanks a lot for the help! Well, so it means that OSGi doesn't really support Servlet 3.0 specification since The problem is that Flow relies on this specification in many many places.
So may be we need to do something specific for OSGi but I think it should be something on our side (additional logic specific for OSGi implemented in Flow). Thank you for your help one more time! |
I have to thank YOU for your effort on this. I know that OSGi can be tough some times, as it requires one to rethink old patterns , which I had to learn the hard way ;) Regarding the
Regarding the "additional logic specific for OSGi implemented in Flow": Regarding "Flow relies on this specification in many many places":
I really hope that this helps, as I (and I think also many others) would love to use Vaadin 11 in my OSGi applications. Kind regards, |
They are quite similar yes, but anyway..... It becomes hard to be aware of all of these things.
I'm afraid that there will be also issues with |
I had a look at those classes and maybe you could solve the issue by replacing them with a BundleTracker that (in an OSGi environment) does the same job as the This would look something like this: // This class is just needed to start and stop the BundleTracker in OSGi
@Component
public class MyExtender {
private BundleTracker tracker;
@Activate
private void activate(BundleContext context){
tracker = new VaadinBundleTracker(context);
tracker.open();
}
@Deactivate
private void deactivate(){
tracker.close();
tracker = null;
}
}
public class VaadinBundleTracker extends BundleTracker{
private Executor executor = Executors.newSingleThreadExecutor();
public VaadinBundleTracker(BundleContext context){
// Bundle.ACTIVE makes this BundleTracker only track Bundles that reach or have already reached the ACTIVE state
super(context, Bundle.ACTIVE, null);
}
@Override
public Object addingBundle(Bundle bundle, BundleEvent event){
// This header must be added to all bundles that have a class with @Route or any other annotation that should be processed
String headerName = (String)bundle.getHeaders().get("Vaadin-OSGi-Extender");
if(headerName != null){
// We use an executor as frameworkmethods should not block or take too long
executor.execute(new Runnable(){
@Override
public void run(){
Wiring wiring = bundle.adapt(BundleWiring.class);
// get all .class resources of this bundle
Collection<String> classes = wiring.listResources("/", "*.class", BundleWiring.LISTRESOURCES_RECURSE);
for(String clazz : classes){
// get the classname from the path and load the class to inspect it further
String className = replaceAll("\\.class$", "").replace('/', '.');
Class<?> classToInspect = bundle.loadClass(className);
// do checks/logic for classes that implement, extend, or have been annotated with Route/RouteAlias/Viewport/etc ...
// that are usually done by the ServletContainerInitialize
}
}
});
}
}
} For this to work, all bundles that have a Route or anything similar must add a "Vaadin-OSGi-Extender" header to their manifest, which is (in my opinion) not as intrusive as an annotation. Nevertheless, the classes that are Hope that helps. Kind regards, |
Just changed my code, as it seems lower letter headers are not accepted. One could also narrow down the classes to load by only loading those in the exported/private packages of the bundle. |
We should first test the approach recommended here #4376 (comment) (thanks @Sandared !) for the routes, and if that works, then use it for every other servlet context initializer we have. That can be left for future issues. |
One thing - if the approach works, it should be tested that the routes from another |
There is no anything specifically done for our code base. But our current tests uses So either this file needs to be removed completely or all Flow initializers should be removed. |
This issue is specific for Jetty in Felix OSGi container (both
org.apache.felix.http.jetty
and jetty osgi boot).May be this is a question of the web server bundle in OSGi and there is nothing to do on our side.
I register the servlet manually via the bundle activator (using
HttpServiceTracker
and manual servlet instance creation).And the application doesn't have any routes available even though I have class with
@Route
annotation.It seems that
RouteRegistryInitializer
doesn't do its job.See #4367 for the servlet registration source code.
The text was updated successfully, but these errors were encountered: