Bug 273078 - [tcf][api] Separate TCF Core from TCF Eclipse Integration
Summary: [tcf][api] Separate TCF Core from TCF Eclipse Integration
Status: RESOLVED FIXED
Alias: None
Product: TCF
Classification: Tools
Component: Core (show other bugs)
Version: unspecified   Edit
Hardware: All All
: P3 enhancement (vote)
Target Milestone: 0.2   Edit
Assignee: Eugene Tarassov CLA
QA Contact: Martin Oberhuber CLA
URL:
Whiteboard:
Keywords: api
Depends on:
Blocks:
 
Reported: 2009-04-21 10:55 EDT by Martin Oberhuber CLA
Modified: 2013-06-05 08:01 EDT (History)
4 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Oberhuber CLA 2009-04-21 10:55:58 EDT
The core TCF Java API and Implementation is capable of running stand-alone without Eclipse. On top of that core implementation, there is a thin layer for adapting to Eclipse.

I'd like to propose separating the Eclipse adaption layer into a separate bundle, and treating the core TCF bundle as a plain Java library (with OSGi Manifest markup). We'd have two separate bundles:
   org.eclipse.tm.tcf          -- the core plain Java TCF implementation
   org.eclipse.tm.tcf.eclipse  -- the Eclipse adaption layer
I think this has several advantages:

1. By means of OSGi specification of execution environment and classpath
   setup, it becomes impossible to accidentally introduce Eclipse dependencies
   into what should be plain Java.

2. Using TCF-core in a plain Java App is much cleaner without Eclipse stuff.

3. In addition to an Eclipse adaption layer, there could also be a plain OSGi
   / Equinox adaption layer which uses declarative services instead of
   extension points.

4. Having a separate Eclipse adaption layer allows fully utilizing Eclipse 
   concepts such as e.g. a dedicated extension point for registering Java
   based services lazily -- without jeopardizing the plain Java implementation.

Doing the actual split seems like a fairly straightforward refactoring which we are ready to make. The only API change would be that Eclpise clients should "require-bundle" org.eclpise.tm.tcf.eclipse rather than tm.tcf.

What do others think about this approach?
Comment 1 Anna Dushistova CLA 2009-04-21 11:02:50 EDT
Sounds like a good idea to me.
Comment 2 Eugene Tarassov CLA 2009-04-21 13:53:51 EDT
(In reply to comment #0)
> ... straightforward refactoring which we are ready to make.

Cool. Go for it.

Comment 3 Eugene Tarassov CLA 2009-04-21 15:34:08 EDT
(In reply to comment #2)
> (In reply to comment #0)
> > ... straightforward refactoring which we are ready to make.
> Cool. Go for it.

On a second thought, the refactoring might be not a straightforward one. Currently TCF code is guaranteed to be properly initialized when it is accessed, because Eclipse adaptation is in the same bundle. If you split, it will become possible to accesses uninitialized TCF, which is error prone and kind of unfriendly to clients. I'm not sure how existing behavior can be reproduced with two bundles.

How about creating a core TCF project which is not a plugin - just regular Java project, and then linking that project source or jars to org.eclipse.tm.tcf plugin. It seems to have all the same advantages, plus 100% backward compatible.
Comment 4 Martin Oberhuber CLA 2009-04-21 15:48:00 EDT
(In reply to comment #3)
> On a second thought, the refactoring might be not a straightforward one.
> Currently TCF code is guaranteed to be properly initialized when it is
> accessed, because Eclipse adaptation is in the same bundle.

Hm... if this is indeed true, what is the initialization story for plain Java (non Eclipse) TCF clients? I don't quite understand what the problem is... is it that just accessing class org.eclipse.tm.tcf.Foo would not call Bundle Activator any more? But then in a plain Java app, Foo must not be accessed without initialization either...

> How about creating a core TCF project which is not a plugin - just regular Java
> project, and then linking that project source or jars to org.eclipse.tm.tcf
> plugin. It seems to have all the same advantages, plus 100% backward
> compatible.

So the single Java project would either build a plain java JAR (thus making sure it's really plain Java), or it would build the bundle. Sounds OK to me, though I'd still like to understand why it is necessary.

Perhaps it would be another option to create a NEW bundle name (org.eclipse.tm.tcf.core) for the plain-Java core and re-export its packages through org.eclipse.tm.tcf (which would just include Eclipse adaptation layer). I'm not exactly sure if my assumption is right, but I could imagine that in the reexport case, accessing a class might start the bundle that's reexporting.
Comment 5 Eugene Tarassov CLA 2009-04-21 16:27:24 EDT
(In reply to comment #4)
> Hm... if this is indeed true, what is the initialization story for plain Java
> (non Eclipse) TCF clients? I don't quite understand what the problem is... is
> it that just accessing class org.eclipse.tm.tcf.Foo would not call Bundle
> Activator any more? But then in a plain Java app, Foo must not be accessed
> without initialization either...

TCF initialization should, at least, include assigning TCF events executer. TCF is completely unusable until it is done.

In plain Java app it is not an issue at all, because one can simply do the initialization in main() method. In Eclipse we don't want to do that, because we should not execute any code from the bundle until it is really needed - lazy loading policy. Fortunately, OSGi provides callback from class loader - the start() method, and TCF is initialized at the very best possible moment - when it accessed for the first time, and everything works fine.

If you move TCF classes into another bundle, to reproduce existing behavior you would need to activate Eclipse adaption bundle when a class from TCF code bundle is loaded. It might be possible to do in OSGi using some bunle listeners, but I'm not sure how. Especially because TCF bundle will not be allowed to refer any OSGi or Eclipse code. It seems much easier just put TCF jar into Eclipse adaption bundle.

> So the single Java project would either build a plain java JAR (thus making
> sure it's really plain Java), or it would build the bundle. Sounds OK to me,
> though I'd still like to understand why it is necessary.
> Perhaps it would be another option to create a NEW bundle name
> (org.eclipse.tm.tcf.core) for the plain-Java core and re-export its packages
> through org.eclipse.tm.tcf (which would just include Eclipse adaptation layer).
> I'm not exactly sure if my assumption is right, but I could imagine that in the
> reexport case, accessing a class might start the bundle that's reexporting.

Re-export might work too.

Comment 6 Martin Oberhuber CLA 2009-04-22 07:40:37 EDT
OK, I understand: at the same time the tcf-core bundle is started, the
tcf-eclipse adaption layer must also be started.

With respect to compatibility, I don't think that this is an issue right now
since we haven't released anything yet. The focus should be on providing the
best technical solution rather than providing any means of backward
compatibility. The current
   org.eclipse.tm.tcf.EventQueue
implementation for instance, which is Eclipse specific, should likely move into
a different package (org.eclipse.tm.tcf.eclipse for instance) to keep the plain
"tcf" namespace clean; so there will likely some breakage of backward
compatibility anyways.

That being said, clients should be encouraged to move from "Require-Bundle" in
their MANIFEST.MF to "Import-Package" in their manifest; and TCF should add
version numbers to package exports. I just filed bug 273236 for this. In the
context of moving to "Import-Package", renaming a bundle would not be an issue
any more.

I think that reexporting might work (still not 100% sure), but I'm also fine with the other suggestion of putting tcf-core into a plain Java (non-plugin) project and re-using the source. Seems to be least disruptive for now, we can defer thinking about more bundle separation later. I wouldn't know how to "link in the source" though... Eugene have you done that before?
Comment 7 Eugene Tarassov CLA 2009-04-23 13:49:59 EDT
(In reply to comment #6)
> With respect to compatibility, I don't think that this is an issue right now
> since we haven't released anything yet.

Sure.

> The focus should be on providing the
> best technical solution rather than providing any means of backward
> compatibility.

Well, I beleive current method of initialization is the best technical solution.

> The current
>    org.eclipse.tm.tcf.EventQueue
> implementation for instance, which is Eclipse specific, should likely move into
> a different package (org.eclipse.tm.tcf.eclipse for instance) to keep the plain
> "tcf" namespace clean;

Sure.

> so there will likely some breakage of backward compatibility anyways.

This does not break any compatibility, because org.eclipse.tm.tcf package is not exported.

> That being said, clients should be encouraged to move from "Require-Bundle" in
> their MANIFEST.MF to "Import-Package" in their manifest; and TCF should add
> version numbers to package exports. I just filed bug 273236 for this. In the
> context of moving to "Import-Package", renaming a bundle would not be an issue
> any more.

OK.

> I think that reexporting might work (still not 100% sure), but I'm also fine
> with the other suggestion of putting tcf-core into a plain Java (non-plugin)
> project and re-using the source. Seems to be least disruptive for now, we can
> defer thinking about more bundle separation later. I wouldn't know how to "link
> in the source" though... Eugene have you done that before?

Linking is not a perfect solution - it would require to define a path variable, which needs to be set every time a workspace is created.

After experimenting with different approaches, I think the least disruptive way to do the split is to put TCF core code into a fragment, e.g. org.eclipse.tm.tcf.core. Everything seems fine, code is nicely exported through the host plug-in.

Do you want me to commit it?

Comment 8 Martin Oberhuber CLA 2009-04-28 15:01:33 EDT
(In reply to comment #7)
> After experimenting with different approaches, I think the least disruptive way
> to do the split is to put TCF core code into a fragment, e.g.
> org.eclipse.tm.tcf.core. Everything seems fine, code is nicely exported through
> the host plug-in.
> 
> Do you want me to commit it?

Yes if you could please commit it - thanks for your investigations!

Initially, having a fragment feels odd because it's always bound to one host bundle; that is, we couldn't easily write an alternative adaption layer (such as "TCF OSGi wrapper") instead of the Eclipse adaption layer.

On the other hand, compared to what we have now it is definitely an improvement splitting into fragment + bundle so I'm much in favor of doing this now. It will give use immediate advantage of avoiding accidental introduction of unwanted dependencies. And, I cannot see any immediate negative impact.

I have a feeling that in the longer run, explicit activation from Eclipse (rather than implicit activation via classloader) might be preferable even though it's API breaking. It would also help with bug 270615. But I'd prefer getting the split done first, and discussing explicit activation in a separate bug.

Thanks!
Comment 9 Eugene Tarassov CLA 2009-04-28 17:42:24 EDT
I have done and committed the refactoring.

No changes in the APIs, but you will need to import new project into workspace on next update: org.eclipse.tm.tcf.core
Comment 10 Martin Oberhuber CLA 2010-05-28 14:11:17 EDT
Bulk update: Marking all TCF fixes from the Galileo period (Jun-2008 until Jun-2009) target 3.1 since they were done along with the TM 3.1 release.
Comment 11 Doug Schaefer CLA 2011-05-17 10:48:30 EDT
Moving bugs to new home for IP log.
Comment 12 Martin Oberhuber CLA 2013-06-05 06:25:40 EDT
Bulk change: Marking all bugs from the TM era (until June 2011) target 0.3