Skip to content
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

Remove JAX-RS Connector (com.eclipsesource.jaxrs) dependency #726

Closed
davidgraeff opened this issue Apr 15, 2019 · 21 comments · Fixed by #1443
Closed

Remove JAX-RS Connector (com.eclipsesource.jaxrs) dependency #726

davidgraeff opened this issue Apr 15, 2019 · 21 comments · Fixed by #1443

Comments

@davidgraeff
Copy link
Member

davidgraeff commented Apr 15, 2019

What does this dependency do?

It scans all OSGi services (by STARTING THEM!!) for JAX-RS @Path or @Provided annotations and adds them to a servlet.

The problems with this dependency

Unfortunately the package is not maintained (no major update since 5 years, no commit in general since 3 years). It is not using newer OSGi features (the entire codebase would shrink by half or more), it uses tycho as its main buildsystem with respective outdated examples, and it does really bad things like actually starting up services to find annotations.

I debugged my Hue Emulation Service for probably 3 hours to find out that double service starts are caused by that bundle. Especially if you do a lot of heavy initialization in activate() (even if async) to throw that away moments later, that adds a lot to OH start up time.

Solution

We have the huge advantage in openHAB, that all our REST endpoints not only are annotated with @Path or @Provided but also implement RestResouce and register themselves to the rest core bean. We can therefore spin up our own servlet in about 20 lines of code without this really badly designed dependency.

Example code (without debouncing/restarting to accommodate for dynamically appearing endpoints):

ResourceConfig resourceConfig = ResourceConfig.forApplicationClass(JerseyApplication.class);

resourceConfig.property(ServerProperties.APPLICATION_NAME, "openHAB");

// don't look for implementations described by META-INF/services/*
resourceConfig.property(ServerProperties.METAINF_SERVICES_LOOKUP_DISABLE, false);

// disable auto discovery (class path scanning)
resourceConfig.property(ServerProperties.FEATURE_AUTO_DISCOVERY_DISABLE, true);
resourceConfig.property(ServerProperties.PROCESSING_RESPONSE_ERRORS_ENABLED, true);

resourceConfig.registerInstances(allOurRestResourceInstancesList);

try {
    Hashtable<String, String> initParams = new Hashtable<>();
    initParams.put("com.sun.jersey.api.json.POJOMappingFeature", "false");
    initParams.put(ServletProperties.PROVIDER_WEB_APP, "false");
    httpService.registerServlet("/rest", new ServletContainer(resourceConfig), initParams, null);
} catch (ServletException | NamespaceException e) {
}

Notes

This dependency is not related to com.eclipsesource.jaxrs.provider.swagger which is also used by openHAB. provider.swagger configures swagger via a properties file and is apart from that unrelated to jax-rs.

davidgraeff pushed a commit to davidgraeff/openhab2-addons that referenced this issue Apr 15, 2019
Because of openhab/openhab-core#726
services are started multiple times. services have been annotated to prevent that
from happening.

The UPnP Server now also works for IPv6 and respects multiple
configured discovery addresses.

Writing configAdmin configuration doesn't tear down the entire
hue emulation service anymore.

Only make the rest endpoints available after everything has been setup
and upnp is running.

Signed-off-by: David Graeff <david.graeff@web.de>
davidgraeff pushed a commit to davidgraeff/openhab2-addons that referenced this issue Apr 25, 2019
Because of openhab/openhab-core#726
services are started multiple times. services have been annotated to prevent that
from happening.

The UPnP Server now also works for IPv6 and respects multiple
configured discovery addresses.

Writing configAdmin configuration doesn't tear down the entire
hue emulation service anymore.

Only make the rest endpoints available after everything has been setup
and upnp is running.

Signed-off-by: David Graeff <david.graeff@web.de>
davidgraeff pushed a commit to davidgraeff/openhab2-addons that referenced this issue Apr 25, 2019
Because of openhab/openhab-core#726
services are started multiple times. services have been annotated to prevent that
from happening.

The UPnP Server now also works for IPv6 and respects multiple
configured discovery addresses.

Writing configAdmin configuration doesn't tear down the entire
hue emulation service anymore.

Only make the rest endpoints available after everything has been setup
and upnp is running.

Signed-off-by: David Graeff <david.graeff@web.de>
davidgraeff pushed a commit to davidgraeff/openhab2-addons that referenced this issue Apr 27, 2019
* Split RESTapi class into logical units (ConfigurationAccess, UserManagement, LightsAndGroups)
* rules support
* scenes support
* schedule support
* New self-test page under /api/status
* Refactor tests: Use jersey JAX-RS server to test without requiring the framework (non OSGi tests)
* Worked around doube-activate problem.

Because of openhab/openhab-core#726
services are started multiple times. services have been annotated to prevent that
from happening.

The UPnP Server now also works for IPv6 and respects multiple
configured discovery addresses.

Writing configAdmin configuration doesn't tear down the entire
hue emulation service anymore.

Only make the rest endpoints available after everything has been setup
and upnp is running.

Signed-off-by: David Graeff <david.graeff@web.de>
@wborn wborn added the REST/SSE label May 22, 2019
@cweitkamp
Copy link
Contributor

Thanks for adding the bounty @J-N-K !

I added the "help wanted" and "PR pending" labels as there already is a pending PR (#739) waiting for someone to jump in and continue working on it.

@maggu2810
Copy link
Contributor

IMHO we should migrate to the usage of the R7 JAX-RS whiteboard pattern.
If the migration is finished, this change will be obsolete.

@davidgraeff You already summarized what the publisher is doing. For reference I would like to add also the following link: https://github.com/hstaudacher/osgi-jax-rs-connector#publisher

I did not test it myself, but what do you think about that idea:

  • Do not try to implement the change you comment here. As it is not necessary if the whiteboard pattern is used.
  • Try to be able to use the old JAX-RS implementation and a R7 JAX-RS Whiteboard implementation at the same time (on transition phase).
  • The Whiteboard pattern requires the OSGi property osgi.jaxrs.resource e.g. by annotate the resources with @JaxrsResource. As this is not present on the "old" REST interface implementations they will not be consumed at all by the whiteboard pattern.
  • Migrated ones should be ignored by the old one: Add a little "hack" to the current publisher implementation so we could mark REST resources to be ignored by the current publisher. The hack should not affect the existing REST resources and the bad behaviour you comment above (it keeps the same as before). The simplest machanism would be to ignore the classes that are annotated with the respective "new" annotations or that service contains the "new" properties.

That way we could use both mechanism for the transition phase and migrate one by one.

WDYT?

@davidgraeff
Copy link
Member Author

The JAX-RS Connector ignores routes with a special annotation (forgot the name).
A R7 whiteboard route could have this annotation until JAX-RS Connector is removed.

My migration PR to the whiteboard pattern did more than just using a different API though.
There is a lot of inconsistency of where DTOs and DTO mappers are located. I partly cleaned that up. Just as a warning, that a "1 by 1" migration will still touch code across different core bundles and probably shift code around.

@maggu2810
Copy link
Contributor

https://github.com/hstaudacher/osgi-jax-rs-connector/blob/master/bundles/com.eclipsesource.jaxrs.publisher/src/com/eclipsesource/jaxrs/publisher/internal/Activator.java#L94-L99

If my reading is correct if a ResourceFilter service is present on activation time, this one is used.
Otherwise the AllResourceFilter is used that uses the following filter itself: "(&(objectClass=*)(!(" + PUBLISH + "=false)))" (https://github.com/hstaudacher/osgi-jax-rs-connector/blob/master/bundles/com.eclipsesource.jaxrs.publisher/src/com/eclipsesource/jaxrs/publisher/internal/AllResourceFilter.java#L24)

At the time I looked at your PR I realized that there is much more cleanup done than just the migration.
Great work! Thank you again.

IMHO it is easier to work with upstream if small and separate (by topic) improvements are provided instead of a big PR that clean ups multiple stuff. That's the reason for my migration path.

@kaikreuzer
Copy link
Member

Afair, the only "problematic" REST endpoints were the ones of the sitemaps (or even more specifically, the subscriptions for sitemap changes).
So if those would be kept for the moment, the rest could be migrated without much need for a step-by-step migration or am I overlooking something?

@maggu2810
Copy link
Contributor

If even only one implementation is kept that requires the old implementation we need a way to use both implementations in parallel.

So, I don't see any reason to require to first migrate all except one. It does not make any difference if we need both in parallel if the migration is step by step.
I assume work can be done by different consumers if the base architectural change has been done to support both implementations.

Another option is to wait for a volunteer that invest all the work to migrate all REST implementation except the sitemap one and do a long review session.

@maggu2810
Copy link
Contributor

I made it! 😉
Migrated to JAX-RS Whiteboard -- also the UI Sitemap REST endpoint.
Created a JAX-RS Whiteboard Swagger 1 generator, so I could drop all the eclipsesource dependencies and the annoying OSGi service impacts.
The openHAB REST Doc UI is working as ever (or perhaps better than before).

@wborn
Copy link
Member

wborn commented Nov 25, 2019

That sounds like a very nice accomplishment! 😄 🥇

@kaikreuzer
Copy link
Member

Sounds awesome, @maggu2810!
I'd suggest to apply this change right after the 2.5 release - until then, we should can imho live with the status quo.

@maggu2810
Copy link
Contributor

maggu2810 commented Dec 4, 2019

I realized that the Web UI "cometvisu" also uses the old JAX-RS implementations:

bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/CvActivator.java:import org.glassfish.jersey.media.sse.SseFeature;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncBinder.java:import org.glassfish.hk2.utilities.binding.AbstractBinder;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncBinder.java:import org.glassfish.jersey.internal.inject.CustomAnnotationLiteral;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncBinder.java:import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncContextDelegateProvider.java:import org.glassfish.jersey.media.sse.SseFeature;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncContextDelegateProvider.java:import org.glassfish.jersey.servlet.spi.AsyncContextDelegate;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/async/BlockingAsyncContextDelegateProvider.java:import org.glassfish.jersey.servlet.spi.AsyncContextDelegateProvider;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/backend/ReadResource.java:import org.glassfish.jersey.media.sse.EventOutput;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/backend/ReadResource.java:import org.glassfish.jersey.media.sse.SseBroadcaster;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/backend/ReadResource.java:import org.glassfish.jersey.media.sse.SseFeature;
bundles/org.openhab.ui.cometvisu/src/main/java/org/openhab/ui/cometvisu/internal/util/SseUtil.java:import org.glassfish.jersey.media.sse.OutboundEvent;

What's your plan?

--

WRT the 2.5.x branches of openhab-webui and openhab2-addons the following bundles needs be migrated:

  • org.openhab.ui.cometvisu
  • org.openhab.ui.cometvisu.php (perhaps not really, but it depends on the previous one)
  • org.openhab.io.hueemulation
  • org.openhab.io.neeo
  • org.openhab.transform.jinja
  • org.openhab.binding.lametrictime
  • org.openhab.binding.neeo
  • org.openhab.binding.nest
  • org.openhab.binding.sleepiq
  • org.openhab.binding.tesla

@wborn
Copy link
Member

wborn commented Mar 29, 2020

I made it! 😉

Will you be creating PR(s) for solving this issue @maggu2810? That would be highly appreciated! There's quite a significant as reward for solving it as well. 🙂

@maggu2810
Copy link
Contributor

Sorry @wborn, but currently I don't plan to put any effort into openHAB development.
There are more important things for me to do right now.

@wborn
Copy link
Member

wborn commented Mar 30, 2020

That's unfortunate to hear @maggu2810, but at least we know someone else will have to put effort into this. Do you perhaps have some branches with your (WIP) changes on GitHub that we can use as source of inspiration?

@kaikreuzer kaikreuzer reopened this Mar 30, 2020
@splatch
Copy link
Contributor

splatch commented Apr 2, 2020

What's take on this one? Is it on the roadmap for 3.0?

@wborn
Copy link
Member

wborn commented Apr 2, 2020

Yes it certainly is. That's why I ask around if there are still contributors looking into fixing it. If there are none I might just have to look into it myself one day. 😉

Any previous efforts regarding this would certainly help. There's also David's branch as source of inspiration.

@kaikreuzer
Copy link
Member

I also would love to see this solved for 3.0 and I would hope that there isn't even too much work left as @maggu2810 apparently already made it work. I very much hope that he can provide us a link to his work, so that somebody can take it over from there instead of starting from scratch, which would be a real pity.

@maggu2810
Copy link
Contributor

maggu2810 commented Apr 10, 2020

@wborn
Copy link
Member

wborn commented Apr 10, 2020

Many thanks for the branch and pointers to commits @maggu2810! I'll certainly have a look at it. 👍

@wborn
Copy link
Member

wborn commented Apr 23, 2020

I started porting those commits to the current code base @maggu2810! Let's hope it results in something useful. 😉

@wborn wborn mentioned this issue Apr 24, 2020
16 tasks
@wborn wborn self-assigned this May 5, 2020
@wborn
Copy link
Member

wborn commented May 14, 2020

We made it! :-) The code by @maggu2810 was also top-notch and reusing it saved a lot of time. 👍

@kaikreuzer
Copy link
Member

Yes, awesome work by @maggu2810, a big thanks to him as well!

@wborn wborn removed their assignment Aug 26, 2020
@wborn wborn added this to the 3.0 milestone Oct 6, 2020
Rosi2143 pushed a commit to Rosi2143/openhab-core that referenced this issue Dec 26, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants