This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 216383 - Dependencies with unknown.binary groupId added when creating a REST service in Maven project
Summary: Dependencies with unknown.binary groupId added when creating a REST service i...
Status: VERIFIED FIXED
Alias: None
Product: webservices
Classification: Unclassified
Component: REST (show other bugs)
Version: 7.2
Hardware: All All
: P2 normal (vote)
Assignee: Denis Anisimov
URL:
Keywords: REGRESSION
Depends on: 217321 217340
Blocks: 219732
  Show dependency tree
 
Reported: 2012-08-03 20:12 UTC by Petr Jiricka
Modified: 2013-01-11 09:59 UTC (History)
8 users (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Patch with a utility method for creating an in-memory Java library (14.89 KB, patch)
2012-08-17 07:58 UTC, Petr Jiricka
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Petr Jiricka 2012-08-03 20:12:30 UTC
1. Create a Maven web project with GlassFish 3.1.2.x as the target.
2. Create a REST service from Patterns; while creating, check the "Use Jersey specific features" checkbox

When you look at pom.xml, it has dependencies from a local repository, with a unknown.binary groupId, and a SNAPSHOT version, e.g.:
<dependency>
    <groupId>unknown.binary</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>SNAPSHOT</version>
    <scope>provided</scope>
</dependency>

This is not good, it should just use the normal remote repository, and a specific version of the library. 

Not sure what's the right way to fix it - maybe we should define a "Jersey from GlassFish" library (analogous to the existing "EclipseLink from GlassFish" library), that would have a pom volume pointing to the correct remote artifacts.
Comment 1 Denis Anisimov 2012-08-06 10:02:13 UTC
(In reply to comment #0)
> 1. Create a Maven web project with GlassFish 3.1.2.x as the target.
> 2. Create a REST service from Patterns; while creating, check the "Use Jersey
> specific features" checkbox
> 
> When you look at pom.xml, it has dependencies from a local repository, with a
> unknown.binary groupId, and a SNAPSHOT version, e.g.:
> <dependency>
>     <groupId>unknown.binary</groupId>
>     <artifactId>jackson-core-asl</artifactId>
>     <version>SNAPSHOT</version>
>     <scope>provided</scope>
> </dependency>
> 
> This is not good, it should just use the normal remote repository, and a
> specific version of the library. 

This is no a problem actually because the file is valid and all works correctly.
This issue is actually duplicate of the issue #209573 .
It has been fixed as a result unnecessary project's classpath extending in JEE6 profile case. But now it reappeared as I've expected after providing a possibility to use COMPILE_ONLY classpath.
I'm not sure about closing it as a duplicate of an issue #209573.
I don't see any way to fix the issue on the IDE side.
> 
> Not sure what's the right way to fix it - maybe we should define a "Jersey from
> GlassFish" library (analogous to the existing "EclipseLink from GlassFish"
> library), that would have a pom volume pointing to the correct remote
> artifacts.
That's an old approach which leads to a number of problems. We've decided to remove such REST library based on GF and rewrite JAX-RS stack without using
this library at all. See an issue #196127 and all mentioned there issues.
Comment 2 Petr Jiricka 2012-08-06 11:25:58 UTC
> This is no a problem actually because the file is valid and all works correctly.

I think this IS a problem, because it is bad practice and non-standard approach from the Maven point of view. The standard approach is to use a remote artefact.

> This issue is actually duplicate of the issue #209573.

That's true, but that issue is too long and confusing, so I suggest let's keep this separate.

> That's an old approach which leads to a number of problems. We've decided to
> remove such REST library based on GF and rewrite JAX-RS stack without using
> this library at all. See an issue #196127 and all mentioned there issues.

Ok, I understand, you are right. I talked to Tomas Zezula (cc'ed) about how to solve this, and he suggests the following:
- Provide our own LibraryImplementation (see project.libraries module) that would be in-memory only and would not be stored on the disk
- This implementation would be constructed using the local jar artefact + correct remote maven coordinates (maven pom volume)
- Create a Library from this LibraryImplementation using LibraryFactory.createLibrary
- Pass this library to ProjectClassPathModifier.addLibraries

Would this work (while avoiding problems described in issue 196127) ? 

Regarding the exact Maven artifacts to use, the following page is useful: http://jersey.java.net/nonav/documentation/latest/chapter_deps.html

Note that there is not a 1-1 correspondence between jar in GF installation and Maven dependency (also because some Maven deps require other jars that will be automatically pulled in). The following dependencies are working for me so far, but we should check with the Jersey team:

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.13</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.13</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.sun.jersey.contribs</groupId>
            <artifactId>jersey-multipart</artifactId>
            <version>1.13</version>
            <scope>provided</scope>
        </dependency>
Comment 3 Denis Anisimov 2012-08-06 12:21:37 UTC
I'm not sure I understand the purpose of such approach.
The purpose of the project's classpath extending with Jersey is :
add Jersey jars into the project COMPILE_ONLY classpath *JERSEY JARS THAT ARE AVAILABLE IN THE TARGET J2EE SERVER*.
So in your case GF bundled with Jersey version 1.13.
I have a number of GF installations : 
GF 3.1.2 bundled with 1.11 version.
GF 3.1.1 bundled with 1.8 version.

Two notices here:
- Is it possible to find required dependency for any Jersey jar in the some remote Maven repository ?
I mean: will they have exactly the same resulting binaries as GF bundled have ?
If no then why we should include them as a dependency : they has a correct good remote repository but they differs from what we want. It may introduce  a problem 
in the runtime where different classes are used instead of requested.
If yes then the question is: what is the algorithm for this ?
Do we need to hardcode such algorithm for each Jersey version and update it with 
each newer version? 
- If such algorithm exists then why it is not used by maven infrastructure automatically when Jersey jars are added via ProjectClassPathModifier ?
I mean here: may be this is a request for Jersey/GF team to provide some way to identify required Jersey jars in the remote repository ( unfortunately I don't know the details how maven infrastructure works respectively extending classpath via ProjectClassPathModifier  ).
Comment 4 Petr Jiricka 2012-08-06 22:35:25 UTC
I am cc'ing Jakub, Vince and Tomas as the experts on GlassFish/Jersey.

> So in your case GF bundled with Jersey version 1.13.

Sorry, that was just an example, I agree that in reality you would use the right version used by a particular version of the server.

> Is it possible to find required dependency for any Jersey jar in the some remote Maven 
> repository ?

No, I don't think there is an automatic way to do this.

> Do we need to hardcode such algorithm for each Jersey version and update it
> with each newer version? 

I think we may need to do this (and there are already Maven coordinates in the xml files under websvc.restlib). The question is where this information should be hardcoded - maybe the GF plugin? I.e. for each GlassFish version, could the GF plugin contain information about the Maven coordinates for the Jersey implementation included in this GF version?
Comment 5 Denis Anisimov 2012-08-07 06:25:14 UTC
(In reply to comment #4)
> I am cc'ing Jakub, Vince and Tomas as the experts on GlassFish/Jersey.
> 
> > So in your case GF bundled with Jersey version 1.13.
> 
> Sorry, that was just an example, I agree that in reality you would use the
> right version used by a particular version of the server.
> 
> > Is it possible to find required dependency for any Jersey jar in the some remote Maven 
> > repository ?
> 
> No, I don't think there is an automatic way to do this.
> 
> > Do we need to hardcode such algorithm for each Jersey version and update it
> > with each newer version? 
> 
> I think we may need to do this (and there are already Maven coordinates in the
> xml files under websvc.restlib). The question is where this information should
> be hardcoded - maybe the GF plugin? I.e. for each GlassFish version, could the
> GF plugin contain information about the Maven coordinates for the Jersey
> implementation included in this GF version?

GF plugin is definitely the only place where such logic has to be located if 
we really want to do this.
Comment 6 Petr Jiricka 2012-08-07 08:31:07 UTC
> GF plugin is definitely the only place where such logic has to be located if 
> we really want to do this.

I don't see any other possibility I must say. Denis, so who should implement this? You or Tomas as the GF plugin owner?
Comment 7 Denis Anisimov 2012-08-07 09:27:23 UTC
(In reply to comment #6)
> > GF plugin is definitely the only place where such logic has to be located if 
> > we really want to do this.
> 
> I don't see any other possibility I must say. Denis, so who should implement
> this? You or Tomas as the GF plugin owner?

Hm, we could divide this task on two parts:
- create memory based library for Jersey jars respectively GF version ( smth. like internal API inside server plugin ).
This is purely server plugin functionality mostly the same as dropped restlib_gfv3xxx library ( see issue #196127 ). It has to depend on GF version.
So this is task for GF plugin owner or GF plugin responsible person.
- change JAX-RS stack for GF server where Jersey jars are added into the project 
using this new approach instead of direct jars from GF addition.
This task is for me. I will do it after previous item resolution.
Comment 8 TomasKraus 2012-08-07 12:43:57 UTC
Are you sure that it is a good idea to change anything in GF already installed modules as a project dependency?
Just imagine that you have 2 project running on the same GlassFish and each of them have it's own JAX-RS stack. Which one will be the 'chosen one' for GlassFish?
Comment 9 Denis Anisimov 2012-08-07 12:57:08 UTC
(In reply to comment #8)
> Are you sure that it is a good idea to change anything in GF already installed
> modules as a project dependency?

Sorry Tomas, I don't understand your question.
There is no proposition to change anything in GF modules. There is a request to 
find appropriate Jersey dependency in maven repository ( which correspond to the 
Jersey version in the GF installation ) and produce memory-based library for these
Jersey jars. I'm not sure that it's possible to find exact binaries in the remote 
maven repository but this is what Petr suggest.

> Just imagine that you have 2 project running on the same GlassFish and each of
> them have it's own JAX-RS stack. Which one will be the 'chosen one' for
> GlassFish?
JAX-RS stack is implemented on the server plugin side. There is 1:1 correspondence between target JEE server and JAX-RS stack.
So JAX-RS stack implementation are actually is a part of server plugin. I'm an owner of it by historical reasons.
So again I don't understand what you care about.
Comment 10 Petr Jiricka 2012-08-07 13:24:38 UTC
> There is no proposition to change anything in GF modules.

Right. Tomas, what this issue is about is: GF plugin should provide information about what jar files (+which version) should be added to compilation classpath of the project. I.e. compilation only, no packaging, no runtime behavior.
Comment 11 TomasKraus 2012-08-07 13:28:26 UTC
Looks like it was a misunderstanding from my side. Thank you for quick
response.

I can add this into my TODO list for 7.3. Unfortunately we are quite busy now
so this should wait until the end of September.

What I can do quite quickly is to provide Jersey version number from manifest in jersey-core.jar. Jersey guys told me it's safe source of Jersey version used in installed GF.
Comment 12 Petr Jiricka 2012-08-17 07:58:00 UTC
Created attachment 123229 [details]
Patch with a utility method for creating an in-memory Java library

Regarding:

> create memory based library for Jersey jars respectively GF version ( smth.
> like internal API inside server plugin ). ... So this is task for GF plugin owner 

I am thinking that the API to create the memory library could be actually quite general, and could potentially be used by other modules like WebLogic; I think there was also a need for this in the Persistence module. So I suggest placing it in some API module like java.api.common.

I created a patch with this implementation - Denis, can you please review whether this is what we need? See the unit test that is a part of the patch for an example of how to use it.

Tomas and Milos, can you please review this as well? Is this correct from the point of view of Ant/Maven projects? Thanks.
Comment 13 Petr Jiricka 2012-08-17 07:59:29 UTC
Cc'ing also Milos - see the previous comment.
Comment 14 Milos Kleint 2012-08-17 09:03:13 UTC
from maven point of view a library with "maven-dependencies" property and optionally "maven-repositories" is ok. As long as the coordinates are real and accessible. unknown binary is not ok in general, it's the last desperate step before utterly failing.
central repository content is preferable, but any non-file protocol repository is ok.
Comment 15 Denis Anisimov 2012-08-17 09:14:30 UTC
(In reply to comment #13)
> Cc'ing also Milos - see the previous comment.

(In reply to comment #12)
> Created attachment 123229 [details]
> Patch with a utility method for creating an in-memory Java library
> 
> Regarding:
> 
> > create memory based library for Jersey jars respectively GF version ( smth.
> > like internal API inside server plugin ). ... So this is task for GF plugin owner 
> 
> I am thinking that the API to create the memory library could be actually quite
> general, and could potentially be used by other modules like WebLogic; I think
> there was also a need for this in the Persistence module. So I suggest placing
> it in some API module like java.api.common.
> 
> I created a patch with this implementation - Denis, can you please review
> whether this is what we need? See the unit test that is a part of the patch for
> an example of how to use it.
> 
> Tomas and Milos, can you please review this as well? Is this correct from the
> point of view of Ant/Maven projects? Thanks.

Yes, I think this is what we need.
One issue here : Ant based project doesn't require "mavendeps" and 
"mavenrepos" parameters.
So they could be null and such values are not handled properly in the code.
Comment 16 Petr Jiricka 2012-08-17 09:38:23 UTC
> One issue here : Ant based project doesn't require "mavendeps" and 
> "mavenrepos" parameters.
> So they could be null and such values are not handled properly in the code.

I was thinking that in that case these parameters would be empty array, not null. But of course allowing null would be an easy change, and probably useful especially for mavenrepos.

But anyway, the whole point of this method is that you don't know in advance if this library will be used in Ant or Maven projects - this will be used in project-independent code. So in practice you should always specify both local files (first three parameters) and Maven coordinates (last two parameters), and the project that receives this library will just take what it wants, no?
Comment 17 Denis Anisimov 2012-08-17 13:04:57 UTC
(In reply to comment #16)
> > One issue here : Ant based project doesn't require "mavendeps" and 
> > "mavenrepos" parameters.
> > So they could be null and such values are not handled properly in the code.
> 
> I was thinking that in that case these parameters would be empty array, not
> null. But of course allowing null would be an easy change, and probably useful
> especially for mavenrepos.
> 
> But anyway, the whole point of this method is that you don't know in advance if
> this library will be used in Ant or Maven projects - this will be used in
> project-independent code. So in practice you should always specify both local
> files (first three parameters) and Maven coordinates (last two parameters), and
> the project that receives this library will just take what it wants, no?

Yes, right.
Comment 18 TomasKraus 2012-08-21 13:04:25 UTC
I made a small utility to retrieve Jersey version string from GlassFish modules.
In web-main trunk we added new libs.toolingSDK library with some common code related to GlassFish module.

org.glassfish.tools.ide.utils.ServerUtils class contains set of static methods to work with GlassFish.
public static String getJerseyVersion(String serverHome) is the one you may want to call.

Having GlassFish for example in /some/path/gf312 (installation root), serverHome will be /some/path/gf312/glassfish and modules are in /some/path/gf312/glassfish/modules.

Hope it will help.
Comment 19 Denis Anisimov 2012-08-21 13:19:16 UTC
(In reply to comment #18)
> I made a small utility to retrieve Jersey version string from GlassFish
> modules.
> In web-main trunk we added new libs.toolingSDK library with some common code
> related to GlassFish module.
> 
> org.glassfish.tools.ide.utils.ServerUtils class contains set of static methods
> to work with GlassFish.
> public static String getJerseyVersion(String serverHome) is the one you may
> want to call.
> 
> Having GlassFish for example in /some/path/gf312 (installation root),
> serverHome will be /some/path/gf312/glassfish and modules are in
> /some/path/gf312/glassfish/modules.
> 
> Hope it will help.

The expected method in the GF plugin should return LibraryImplementation 
via createTransientJavaLibraryImplementation method from Petr's patch.
The question is not just GF bundled Jersey version but overall library content :
jar files collections along with maven references .
This is requested GF plugin functionality. All this information is GF 
version specific, that's why it has to be provided by GF plugin internals.

So the expected functionality should be generally the same as removed
restlib_gfv3xxx library ( see issue #196127 ). The only difference is memory 
based library ( requested ) against of static IDE registered.

So is there such method available ?
Comment 20 Petr Jiricka 2012-08-21 13:22:12 UTC
Denis is right, what's needed is exact Jersey library content per GF version.

BTW, Tomas, where are the sources of the Tooling SDK? Thanks.
Comment 21 TomasKraus 2012-08-21 13:39:57 UTC
I'll copy paste it here too ... 

We already made API to setup list of jars to be passed as Library from GlassFish as part of our new cloud support module. It's also part of that libs.toolingSDK.
But it's bit more complicated and looks like I'll have to make some additional changes because now it uses static configuration.

Generally it allows us to configure set of GlassFish libraries (the ones from J2EE J2eePlatformImpl SPI) using XML files. Adding Jersey means just to add new patterns into those XML files.

SDK side:
---------
org.glassfish.tools.ide.server.config.LibraryBuilder is public API.
1) It's configured using public static void init(URL defaultConfig, Config... nextConfig) before 1st usage. You have to provide set of XML files containing Libraries definition.

2) LibraryBuilder instance allows to search given directory tree using patterns from XML file.

Application side (NB):
----------------------
Check glassfish.cloud project in trunk. Especially org.netbeans.modules.glassfish.cloud.javaee.GlassFishPlatformImpl#getLibraries for how this SDK API is used.

1) static LibraryBuilder.init(...) method is called in GlassFishPlatformImpl static initializer with XML files containing libraries configurations (gfLibsDefault for old ones and gfLibs4.xml since GF 4.0.0).

2) public LibraryImplementation[] getLibraries() will provide list of JARs based on concrete GlassFish installation using LibraryBuilder instance.

TODO:
-----
Make configuration to be non static (some 'config' object instance passed to LibraryBuilder constructor.
Create set of config XML files for Jersey in known Glassfish servers.

I'm working on changing configuration to be non static now. 

Tooling SDK repository is private at this moment, you got it in e-mail.
Comment 22 TomasKraus 2012-08-21 14:55:34 UTC
Problem with builder configuration is resolved.
Static LibraryBuilder.init method (storing list of XML files in Class LibraryBuilder context) was replaced by LibraryConfig class constructor which contains XML files mapped to individual GlassFish versions.
LibraryBuilder instance is then passed to LibraryBuilder constructor.

hg.netbeans.org/web-main/
-------------------------
changeset:   230438:8ce778ef4a1b
summary:     Library builder configuration is not static.

I also talked to Peter and looks like I had to implement 2 more things:
1) Allow XML files to contain web links (for javadoc)
2) Add one more section for maven. Now we support only classpath/javadoc/sources as it was in JavaEE SPI.
Comment 23 Tomas Zezula 2012-08-21 16:11:20 UTC
There is already an API covering such a usecase:

LibraryImplementation impl = LibrariesSupport.createLibraryImplementation(type, volumeIds);
assert impl3 instanceof LibraryImplementation3;
LibraryImplementation3 impl3 = (LibraryImplementation3) impl;
impl.setContent(....);
....
impl.getProperties().put(...);
Library lib = LibraryFactory.createLibrary(impl);


The TransientLibraryImplementation is not needed. The added factory method in CommonProjectUtils seems good to me as a support method which can delegate to LS.cLI(). I will add it.
Comment 24 Petr Jiricka 2012-09-07 15:55:06 UTC
The new API CommonProjectUtils.createJavaLibraryImplementation per issue 217340 is already in trunk, so the next step is to use it in the GlassFish plugin, right? Assigning to Tomas as the next step is up to him.
Comment 25 TomasKraus 2012-09-10 15:08:54 UTC
I already did some steps to implement it. I'll let you know when this is done.
Comment 26 Petr Jiricka 2012-10-11 11:30:04 UTC
P2 bug 219732 depends on this -> changing priority to P2.
Comment 27 Petr Hejl 2012-10-15 10:36:40 UTC
Denis, is anybody else going to use the in-memory library? Should it be part of J2eePlatformImpl.getLibraries()? If not all the logic should be placed in JaxRsStack (I'm not talking about who should do that, just about the contract and code location).
Comment 28 Denis Anisimov 2012-10-15 10:55:26 UTC
(In reply to comment #27)
> Denis, is anybody else going to use the in-memory library? Should it be part of
> J2eePlatformImpl.getLibraries()? 
I don't think so.
> If not all the logic should be placed in
> JaxRsStack (I'm not talking about who should do that, just about the contract
> and code location).
Probably this is the most appropriate place for it.
We already have NB bundled Jersey library. It has to be used as official Jersey
library across projects to keep portability.
Server based Jersey ( plugin dependent ) is intended to be used only with REST
functionality to avoid extending project's COMPILE classpath ( to avoid packaging 
them with web application ). This Jersey library is very specific to the target
server and its JaxRs support.
So they should not be visible to the end user via any public API.
It's internal implementation of JaxRs stack.
The request is very similar to having "restlib_gfv3xxx" library. 
But on the opposite of "restlib_gfv3xxx library" it shouldn't be publicly 
available and registered via LibraryManager ( it should be in-memory library ).

So I think JaxRsStack implementation is a correct place for this logic.
Comment 29 TomasKraus 2012-11-19 09:34:43 UTC
NetBeans web-main:
------------------
changeset:   238983:68a14494daa4
summary:     216383 - Jersey library builder

GF Tooling SDK:
---------------
changeset:   353:3a865ac851e0
summary:     Bug# 216383 - Jersey library builder
Comment 30 TomasKraus 2012-11-19 10:01:06 UTC
New class
org.netbeans.modules.glassfish.javaee.JerseyLibrary was introduced in glassfish.javaee module.

Method public Library getLibrary() will return Jersey library from GlassFish modules using new GF Tooling SDK framework.

I did not integrate this with
org.netbeans.modules.glassfish.javaee.Hk2JavaEEPlatformImpl.JaxRsStackSupportImpl
yet, because it's 2 weeks before final code freeze and I won't risc any regressions in this state of release cycle.
This should be done for next release.
Comment 31 Petr Jiricka 2012-11-19 10:27:44 UTC
> ...and I won't risc any regressions in this state of release cycle.
> This should be done for next release.

No, it must be done in this release, because this already IS a regression. Code that looks for jar files inside server installation and adds them to library manager should not be risky - if it's risky, then it's problematic design of this code.
If you are not sure about changes to JaxRsStackSupportImpl, then please leave it up to Denis.
Comment 32 TomasKraus 2012-11-19 15:17:59 UTC
NetBeans web-main:
------------------
changeset:   239532:f21ca5e3f93c
summary:     #216383 - Jersey library builder extended to support Java EE, 
             JAX-RS and Jersey libraries

org.netbeans.modules.glassfish.javaee.JerseyLibrary renamed to Hk2LibraryProvider.
Added methods to get Java EE and JAX-RS, renamed Jersey related method.
Comment 33 TomasKraus 2012-11-20 16:09:48 UTC
Passing back to Dennis to evaluate my changes and finish what's needed.
Comment 34 Quality Engineering 2012-11-21 13:41:16 UTC
Integrated into 'main-golden', will be available in build *201211211016* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Changeset: http://hg.netbeans.org/main-golden/rev/f21ca5e3f93c
User: Tomas Kraus <TomasKraus@netbeans.org>
Log: #216383 - Jersey library builder extended to support Java EE, JAX-RS and Jersey libraries
Comment 35 Denis Anisimov 2012-11-21 17:56:53 UTC
web-main#d2495fc3a677
Comment 36 Quality Engineering 2012-11-22 02:44:13 UTC
Integrated into 'main-golden', will be available in build *201211220002* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress)
Changeset: http://hg.netbeans.org/main-golden/rev/d2495fc3a677
User: Denis Anisimov <ads@netbeans.org>
Log: Fix for BZ#219732 - Creating REST service with Jersey specific features results in absolute paths in project.properties  and BZ#216383 - Dependencies with unknown.binary groupId added when creating a REST service in Maven project