Bug 246448 - Need more extensible library provider framework
Summary: Need more extensible library provider framework
Status: RESOLVED FIXED
Alias: None
Product: WTP Common Tools
Classification: WebTools
Component: Faceted Project Framework (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows XP
: P3 enhancement (vote)
Target Milestone: 3.1 M3   Edit
Assignee: Konstantin Komissarchik CLA
QA Contact:
URL:
Whiteboard:
Keywords: plan
Depends on:
Blocks: 128091
  Show dependency tree
 
Reported: 2008-09-05 18:39 EDT by Konstantin Komissarchik CLA
Modified: 2008-10-25 00:02 EDT (History)
11 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Konstantin Komissarchik CLA 2008-09-05 18:39:47 EDT
Management of libraries can get pretty tricky, particularly when tooling doesn't ship with libraries and relies on getting the libraries elsewhere. There are many different ways of bundling and distributing libraries. It is impossible for central tooling to account for all the possibilities. Application servers make this situation even more complicated. Not only do you have to account for libraries on project classpath, but also libraries being available at runtime. Many of the methods of provisioning libraries on a particular application server are proprietary.

High-Level Requirements:

Create a highly-flexible library provider framework that would completely insulate facet implementation from the details of how libraries are found, configured in the project or deployed at runtime.

1. Library provider needs to be able to execute arbitrary code when libraries are installed or uninstalled. Library provider might want to modify classpath, edit some descriptor files, copy jars into project, etc. The framework should not make any assumptions regarding what it might take to configure libraries in a project.

2. Facet needs to be able to determine the library providers that are applicable in the current context (based on facets selected, targeted runtime, etc.)

3. Facet needs to be able to let the user choose the library provider to use without knowing details about specific library providers.

4. Library provider needs to be able to show configuration UI when it is being selected on facet installation. 

5. Other facet lifecycle events (such as uninstall and version-change) need to be handled.

Goals:

The main driver for this is to enable better integration of commercial adopter products with WTP's Dali and JSF facets. Oracle has an existing framework in a commercial product that handles these requirements and we are looking into putting into open source (after any adjustments that are necessary) where it can be leveraged by Dali and JSF teams.
Comment 1 Konstantin Komissarchik CLA 2008-09-05 18:41:32 EDT
JSF Bug 128091 might be addressed by this effort. Are there any others?
Comment 2 Cameron Bateman CLA 2008-09-05 18:54:56 EDT
(In reply to comment #1)
> JSF Bug 128091 might be addressed by this effort. Are there any others?

To be more specific, the second item, vis "Different IRuntime targets..." could be solved by the new framework.  The other three issues are not specifically related to runtime items.
Comment 3 Konstantin Komissarchik CLA 2008-09-05 19:48:04 EDT
> > JSF Bug 128091 might be addressed by this effort. Are there any others?
> 
> To be more specific, the second item, vis "Different IRuntime targets..." 
> could be solved by the new framework.  The other three issues are not 
> specifically related to runtime items.

The other requirements might be addressed by it as well. For instance, copying CSS files associated with a library or modifying web.xml is within scope of what the libraries provider framework enables.
Comment 4 Konstantin Komissarchik CLA 2008-10-08 21:43:33 EDT
The work on this is pretty much completed. Just down to a few loose bugs here and there.

The new framework consists of API in the following packages:

org.eclipse.jst.common.project.facet.core.libprov
org.eclipse.jst.common.project.facet.core.libprov.user
org.eclipse.jst.common.project.facet.ui.libprov
org.eclipst.jst.common.project.facet.ui.libprov.user

and the following extension points:

org.eclipse.jst.common.project.facet.core.libraryProviders
org.eclipse.jst.common.project.facet.core.legacyLibraryProviderDetectors
org.eclipse.jst.common.project.facet.ui.libraryProviderActionPanels

The code is in and documented for the most part. Review and provide feedback.

I will open separate bugs to track integration with JSF and Dali facets.
Comment 5 Konstantin Komissarchik CLA 2008-10-08 21:50:48 EDT
JSF Integration : Bug 250208
JPA Integration : Bug 250210
Comment 6 Eugene Kuleshov CLA 2008-10-22 15:12:45 EDT
Konstantin, can you please elaborate how this framework can coexist and reuse libraries/jars managed by other tools (e.g. Maven)? Thanks.
Comment 7 Konstantin Komissarchik CLA 2008-10-22 15:19:46 EDT
Hi Eugene,

There is basically two ways that something like Maven could work with this:

1. There will be an option to either disable library configuration for a facet (see Max's mockup in Bug 250208) or there might be a "Let me manage my own libraries" provider that essentially no-ops.

2. It's also possible for the projects that tool Maven in Eclipse to write a Maven library provider implementation. This library provider could do whatever is necessary to make sure that project is properly configured to use say a JSF library via Maven. It might add (or check that it's already preset) the Maven classpath container, it might add entries to pom, etc.

Let me know if that didn't answer you questions.
Comment 8 Eugene Kuleshov CLA 2008-10-22 16:20:21 EDT
(In reply to comment #7)
> Let me know if that didn't answer you questions.

Well, I am not sure. I've tried to bring up this issue before, but allow me to reiterate.

Let's say there is no Eclipse, but we have some project that already builds from the command line. So, build tool already been able to resolve its dependencies to compile code and then run tests, i.e. jars are around and they are known.

Now we need to import project into Eclipse to work on the code. It would be natural to use the same dependencies as in the command line, so JDT allows that with its classpath containers and then WTP allows to declare the rest using its own API (which cause some issues like duplicated dependencies, because of the overlap with JDT classpath).

Once that is done, we need to enable specific tools on that project. Presumably those tools somehow map to the "facets" and that is when several problems occur.

First of all it is unclear what is the scope of the wtp "runtimes" (compile, test, or runtime or something else?), i.e. if project need to be tested with Tomcat or JBoss, it doesn't mean that Tomcat/JBoss classes need to be in the project compile classpath (api vs. vendor-specific classes)

Also, how one could tell what tools/facets need to be enabled on given project? I suppose we can look at the actual project dependencies used by command line build and deduce/map specific tools (JSF, JPA, Spring, etc) based on presence of certain dependnecies/jars. But then if tool need some libraries they need to come from the same place as in the command line build.

As you can see I have more questions then answers and hope you can help me to find a solution for those issues.
Comment 9 Konstantin Komissarchik CLA 2008-10-22 18:34:31 EDT
> First of all it is unclear what is the scope of the wtp "runtimes" (compile, 
> test, or runtime or something else?), i.e. if project need to be tested with 
> Tomcat or JBoss, it doesn't mean that Tomcat/JBoss classes need to be in the 
> project compile classpath (api vs. vendor-specific classes)

The job of the runtime (as distinct from a server instance) is to provide a target to compile project source against and to serve as the reference point for which capabilities the runtime environment supports. The job of the server is to publish and run applications.

Regarding separation of standard vs proprietary interfaces, very early on we discussed shipping J2EE interface libraries with WTP so that they can serve as compilation target for users wanting pure standards implementation, but there are licensing issues standing in the way. 

The existing solution is to let the runtime supply the classpath for a facet (especially root module facets) in whatever way the runtime provider sees fit. Some add practically every jar that's available. Some add only standards-based interfaces. Typically, vendors also include in their tooling a standards extensions facet that controls whether user can access non-standard features. For instance, for WebLogic Oracle adds "WebLogic Web App Extensions" facet to web apps. If you don't install, you don't get proprietary features (at least in theory).

> Also, how one could tell what tools/facets need to be enabled on given 
> project? I suppose we can look at the actual project dependencies used by 
> command line build and deduce/map specific tools (JSF, JPA, Spring, etc) 
> based on presence of certain dependnecies/jars. But then if tool need some 
> libraries they need to come from the same place as in the command line build.

Let's say you write a "Maven Library" provider for JSF and JPA that knows how to add m2eclipse classpath container to project classpath (if it's not there already) and how to add library entries for JSF/JPA to pom (if they are not there already).

Once you have that, you have solved the usecase where the user starts with a maven app that doesn't have JSF/JPA support yet and can easily add that via tooling. The pom is modified, so tooling and command line world stay in sync.

Then as part of "import maven projects" wizard you can add some code that identifies the dependencies of the app. The wizard could then configure the relevant facets (JSF, JPA, etc.). Since in this case you are running facet installation headless from your wizard you can configure facet installation config objects to use your new Maven library provider (there is api for picking the library provider). Once facets are installed, the project is configured properly for maven use.
Comment 10 Eugene Kuleshov CLA 2008-10-22 19:09:59 EDT
(In reply to comment #9)
> The job of the runtime (as distinct from a server instance) is to provide a
> target to compile project source against and to serve as the reference point
> for which capabilities the runtime environment supports.

I believe this "and" cause most of the issues now. There is several independnet sets of configuration:

* server instance where project need to be deployed to
* set of facets/features enabled for given project

It should be possible to tell if given server supports selected facets or not and facets give an indication which libraries are required at the build time and if there is some additional libraries are needed for some other needs. So, "runtime" abstraction is somewhat redundant, but maybe I am missing something.

> Regarding separation of standard vs proprietary interfaces, very early on we
> discussed shipping J2EE interface libraries with WTP so that they can serve as
> compilation target for users wanting pure standards implementation, but there
> are licensing issues standing in the way. 

That won't be necessary if some kind of provider associated with a facet, e.g. one that could grab libraries from the server instance, or one that would use Maven-based dependency resolution. Is it what proposed feature is going to do?

> For instance, for WebLogic Oracle adds "WebLogic Web App Extensions" facet to
> web apps. If you don't install, you don't get proprietary features (at least
> in theory).

That makes sense, but then again, someone could just add those jars into JDT build path without any special facets.

> Let's say you write a "Maven Library" provider for JSF and JPA that knows how
> to add m2eclipse classpath container to project classpath (if it's not there
> already) and how to add library entries for JSF/JPA to pom (if they are not
> there already).

I really would like to avoid implementing separate "maven library" providers for each individual Eclipse tool.

Users have many ways to declare individual JSF/JPA dependencies in the Maven pom (e.g. different versions, different reference implementations, different vendors, etc), so generally we don't know which project dependencies belong to given tool and in my understanding it is not necessarily going to work for all projects if JSR/JPA tools would just pickup JDT compile-time classpath.
 
> Once you have that, you have solved the usecase where the user starts with a
> maven app that doesn't have JSF/JPA support yet and can easily add that via
> tooling. The pom is modified, so tooling and command line world stay in sync.

Can you please explain this? Project is already building and testing from the command line, so obviously all required dependencies are already declared in the pom. The question is how JSF/JPA tools would get those dependencies?
Comment 11 Konstantin Komissarchik CLA 2008-10-22 19:57:52 EDT
> > The job of the runtime (as distinct from a server instance) is to 
> > provide a target to compile project source against and to serve as the 
> > reference point for which capabilities the runtime environment supports.
> 
> I believe this "and" cause most of the issues now. There is several independnet 
> sets of configuration:
> 
> * server instance where project need to be deployed to
> * set of facets/features enabled for given project
> 
> It should be possible to tell if given server supports selected facets or not 
> and facets give an indication which libraries are required at the build time 
> and if there is some additional libraries are needed for some other needs. 
> So, "runtime" abstraction is somewhat redundant, but maybe I am missing 
> something.

This is really rather of a tangent from the purpose of this bug... Every server is a runtime. Not every runtime is a server. Consider that for some app servers there is a distinction between an installation (which is sufficient to tell you about the capabilities and provide libraries) and a configure runnable instance (there could be many of these). 

> > Regarding separation of standard vs proprietary interfaces, very early 
> > on we discussed shipping J2EE interface libraries with WTP so that 
> > they can serve as compilation target for users wanting pure standards 
> > implementation, but there are licensing issues standing in the way.
> 
> That won't be necessary if some kind of provider associated with a facet, e.g.
> one that could grab libraries from the server instance, or one that would use 
> Maven-based dependency resolution. Is it what proposed feature is going to do?

Exactly. The library provider framework gives you options and extensibility.

> > For instance, for WebLogic Oracle adds "WebLogic Web App Extensions" 
> > facet to web apps. If you don't install, you don't get proprietary 
> > features (at least in theory).
> 
> That makes sense, but then again, someone could just add those jars into JDT 
> build path without any special facets.

Of course. But whether the rest of the tooling recognized the jars and enables functionality is a different matter entirely.

> > Let's say you write a "Maven Library" provider for JSF and JPA that 
> > knows how to add m2eclipse classpath container to project classpath 
> > (if it's not there
> > already) and how to add library entries for JSF/JPA to pom (if they 
> > are not there already).
> 
> I really would like to avoid implementing separate "maven library" providers > for each individual Eclipse tool.
> 
> Users have many ways to declare individual JSF/JPA dependencies in the Maven 
> pom (e.g. different versions, different reference implementations, different 
> vendors, etc), so generally we don't know which project dependencies belong 
> to given tool and in my understanding it is not necessarily going to work for 
> all projects if JSR/JPA tools would just pickup JDT compile-time classpath.

The framework gives you a lot of flexibility regarding how to solve this problem. Your maven provider would have ability to contribute UI that user interacts with for configuring various parameters if these parameters are not obvious based on context. You should take a look at the API referenced in this bug (already in WTP code stream) and play around with the patch for the JSF facet (Bug 250208).

> > Once you have that, you have solved the usecase where the user starts 
> > with a maven app that doesn't have JSF/JPA support yet and can easily 
> > add that via tooling. The pom is modified, so tooling and command line 
> > world stay in sync.
> 
> Can you please explain this? Project is already building and testing from the 
> command line, so obviously all required dependencies are already declared in 
> the pom. The question is how JSF/JPA tools would get those dependencies?

I tried to present separate usecases that perhaps got intertwined somewhat. In one use case, you start with a fully-configured app that at the pom-level knows about the libraries. In this situation, the job of the maven library provider is perhaps only to validate things. In the second case, the project doesn't use JSF/JPA functionality yet (in tools or on command line). For that scenario, the maven library provider could help the user configure both project classpath (by adding the m2eclipse container if it's not there already) and make changes to pom to reference the library. Perhaps some user input is needed to know what to reference. Many possibilities. Try playing a little with the framework. It will become more clear.
Comment 12 Eugene Kuleshov CLA 2008-10-22 20:33:20 EDT
(In reply to comment #11)
> This is really rather of a tangent from the purpose of this bug... Every
> server is a runtime. Not every runtime is a server. 

Exactly, but facets still should give a good idea what jars are needed for them at compile time and potentially at other times, such as execution.

> > That makes sense, but then again, someone could just add those jars into
> > JDT build path without any special facets.
> Of course. But whether the rest of the tooling recognized the jars and enables
> functionality is a different matter entirely.

That is kind of my point. Tools should not be using compile-time classpath for something that is outside of compilation. They should have their own separate "sandbox" with own classpath for their own needs.

> The framework gives you a lot of flexibility regarding how to solve this
> problem. Your maven provider would have ability to contribute UI that user
> interacts with for configuring various parameters if these parameters are not
> obvious based on context. You should take a look at the API referenced in this
> bug (already in WTP code stream) and play around with the patch for the JSF
> facet (Bug 250208).

The thing is that most users simply won't know how to use such configuration and it is our responsibility to configure things for them in the first place.
 
> Try playing a little with the framework. It will become more clear.

Unfortunately I won't have time to actually play with this code, at least not in the next few month. Would it be too much to ask to look at our wtp integration and see how it fits with this new stuff?
Comment 13 Konstantin Komissarchik CLA 2008-10-22 20:45:26 EDT
> Unfortunately I won't have time to actually play with this code, at least not
> in the next few month. Would it be too much to ask to look at our wtp
> integration and see how it fits with this new stuff?

I certainly don't have the bandwidth to do that, but if someone else wants to volunteer...
Comment 14 Konstantin Komissarchik CLA 2008-10-25 00:02:31 EDT
Added a runtime library provider to properly bridge to the old runtime classpath provider API. This library provider will only be enabled if the project targets a runtime and if that runtime is configured to provide library for the JSF facet. In that situation user will see "Library Provided by Target Runtime" in the type combo box and the panel beneath the combo box will show a label that reads:

"The targeted runtime is able to provide the library required by this facet. Selecting this option will configure the project to use that library."

The runtime library provider is global. Facet-specific configuration is not required. The runtime library provider has higher priority than user library provider, so in a clean workspace it will be selected by default if enabled.

Tested the positive case using JBoss 5.0 and JBoss Tools 3.0 Alpha1. Tested the negative case by de-selecting a runtime and by selecting Tomcat.