Inconsistency range version between Gradle declaration and MANIFEST file

thumbnail
Enrico Oliosi, modified 7 Years ago. Junior Member Posts: 73 Join Date: 7/6/10 Recent Posts

Good morning. I am testing version range into build.gradle file, I configured the project like this:

[...]
    dependencies {
        compileOnly group: "com.liferay.portal", name: "com.liferay.portal.kernel", version: "[2.6.0,2.13.0)"
        compileOnly group: "com.liferay.portal", name: "com.liferay.util.taglib", version: "2.10.9"
        compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
[...]

I specify to Gradle to get portal-kernel.jar included between versions 2.6.0 (included) and 2.13.0 (excluded).

When I build (with "blade gw build" - I am using liferay workspace) my project Gradle downloads portal-kernel 2.13.0-SNAPSHOT jar and use this artifact to calculate package interval to create MANIFEST.MF of my project.

 

Into MANIFEST.MF I have:

Import-Package: com.liferay.portal.kernel.portlet.bridges.mvc;version= "[1.4,2)",[...]

but this translation is wrong, because I don't want 1.4 version of "com.liferay.portal.kernel.portlet.bridges.mvc". Infact these are "com.liferay.portal.kernel.portlet.bridges.mvc" versions for the different portal-kernel.jar versions:

portal-kernel 2.6.0 exports com.liferay.portal.kernel.portlet.bridges.mvc;version="1.2.0"

portal-kernel 2.12.0 exports com.liferay.portal.kernel.portlet.bridges.mvc;version="1.3.0"

portal-kernel 2.13.0-SNAPSHOT exports com.liferay.portal.kernel.portlet.bridges.mvc;version="1.4.0"

portal-kernel 2.13.0 exports com.liferay.portal.kernel.portlet.bridges.mvc;version="1.4.0"

Why does it use 2.13.0-SNAPSHOT and not 2.12 of the portal kernel? Why does it use version "[1.4" and not "[1.3" of "com.liferay.portal.kernel.portlet.bridges.mvc" package?

 

Thanks.

Enrico

thumbnail
Milen Dyankov, modified 7 Years ago. Expert Posts: 310 Join Date: 10/30/12 Recent Posts

It is in fact correct behavior, even though not the one you want !

 

Why does it use 2.13.0-SNAPSHOT and not 2.12 of the portal kernel?

Because you told it to do so in your gradle file. The 2.13.0-SNAPSHOT is the most recent one with respect to the [2.6.0,2.13.0) interval. 

 

Why does it use version "[1.4" and not "[1.3" of "com.liferay.portal.kernel.portlet.bridges.mvc" package

Because 1.4.0 is the version of the package exported by 2.13.0-SNAPSHOT bundle. 

 

I guess what you need is to tell Gradle to not use SNAPSHOT dependencies. But I have no idea how to do that in Gradle. 

thumbnail
Minhchau Dang, modified 7 Years ago. Liferay Master Posts: 598 Join Date: 10/22/07 Recent Posts
Milen Dyankov:

I guess what you need is to tell Gradle to not use SNAPSHOT dependencies. But I have no idea how to do that in Gradle. 

A quick search indicates it's not trivial. There's a gist from Andrea that tries to demonstrate how to do it by customizing the Gradle resolution strategy.

Enrico Oliosi:

Good morning. I am testing version range into build.gradle file, I configured the project like this:

Which leads me to ask the question: why are you using version ranges? Maybe I'm overly paranoid, but version ranges make your build non-repeatable and introduce security risks (like what happens whenever npm releases are compromised, since node.js developers tend to use version ranges on their dependencies), so to me, there needs to be a compelling reason not to specify a fixed version.

thumbnail
Enrico Oliosi, modified 7 Years ago. Junior Member Posts: 73 Join Date: 7/6/10 Recent Posts
Minhchau Dang:

Which leads me to ask the question: why are you using version ranges? Maybe I'm overly paranoid, but version ranges make your build non-repeatable and introduce security risks (like what happens whenever npm releases are compromised, since node.js developers tend to use version ranges on their dependencies), so to me, there needs to be a compelling reason not to specify a fixed version.

Yep Minhchau, you're right, but reading this article written by David (where he cites Milen also), he describes a scenario where the range version could be a need.

 

 

 

 

thumbnail
Minhchau Dang, modified 7 Years ago. Liferay Master Posts: 598 Join Date: 10/22/07 Recent Posts

Yep Minhchau, you're right, but reading this article written by David (where he cites Milen also), he describes a scenario where the range version could be a need.

Aha. The main thrust of that blog post was, "You always want to pick the oldest version you can get away with (relative to the major version number)." Always a fixed version (for repeatable builds), as old as possible (so you can get the widest possible bnd-generated package version range).

I believe "Completely transparent upgrades because my version ranges control where the code runs!" was a joke that was lost in translation. You don't usually get transparent upgrades from changing your Gradle except in very specific circumstances (which you could also achieve with bnd.bnd changes), and usually they're unexpected (like with terms of use content providers).

thumbnail
David H Nebinger, modified 7 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts

And to carry the thought further, I only use version ranges in my bnd.bnd file.

In the build.gradle file, you're specifically choosing a version that has the API that you want to compile against, but that is a direct compile-time dependency.

The runtime version range, defined in your bnd.bnd file, defines the version of the package that you are okay to bind against.

> I believe "Completely transparent upgrades because my version ranges control where the code runs!" was a joke that was lost in translation.

No, I wasn't really joking there...

If I have two bundles, one bnd.bnd says it has an Import-Package range on com.liferay.portal.kernel.dao.search from (2.6.0,2.13.0] and I have a second module that has the Import-Package range from (2.13.0,3.0.0], only one of these will be satisfied and will be active at any given time.  I can deploy both modules to a Liferay instance and forget about it.  If the version is 2.10.0 when I first deploy the modules, only the first one will be active.  If a fixpack is deployed that increases the version to 2.20.0, the second one will be the active one.

So even though the portal upgrades, it is transparent to my code because I have two bundles deployed to take advantage of the available version.

I don't know how often that really happens, though.  I tend to do FPs in the lower lanes far in advance of what goes to prod, but rarely does my code need to be deployed to the higher lanes ahead of FP promotion.

Who knows, maybe folks out there take a long time to thoroughly test the fix packs, so if their custom code gets updated and deployed ahead of the FP promotions, this can be a way to have your deployed code that is compatible with both versions...

thumbnail
David H Nebinger, modified 7 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts
Enrico Oliosi:

But reading this article written by David (where he cites Milen also), he describes a scenario where the range version could be a need.

Sorry about the confusion on that, Enrico.

I've updated the post and put a section at the bottom explaining the use of a version in your build.gradle file vs declaring a version range in the Import-Package directive in your bnd.bnd file.

 

 

 

 

thumbnail
Enrico Oliosi, modified 7 Years ago. Junior Member Posts: 73 Join Date: 7/6/10 Recent Posts
Milen Dyankov:

It is in fact correct behavior, even though not the one you want !

 

Why does it use 2.13.0-SNAPSHOT and not 2.12 of the portal kernel?

Because you told it to do so in your gradle file. The 2.13.0-SNAPSHOT is the most recent one with respect to the [2.6.0,2.13.0) interval. 

 

I guess what you need is to tell Gradle to not use SNAPSHOT dependencies. But I have no idea how to do that in Gradle. 

Hi Milen, I created a project using Liferay workspace anche another without it. I used the same Gradle version (4.4.1) and I got this scenario:

 

//With LF workspace and&nbsp;Gradle version 4.4.1<br> λ blade gw dependencies | grep "com.liferay.portal.kernel"<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.13.0-SNAPSHOT<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.13.0-SNAPSHOT<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.13.0-SNAPSHOT


//...without LF workspace and&nbsp;Gradle version 4.4.1<br> λ &nbsp;./gradlew budapest:dependencies | grep "com.liferay.portal.kernel:"<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.12.0<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.12.0<br> +--- com.liferay.portal:com.liferay.portal.kernel:[2.6.0,2.13.0) -&gt; 2.12.0

 

There is something that I am not able to catch...

 

 

thumbnail
David H Nebinger, modified 7 Years ago. Liferay Legend Posts: 14933 Join Date: 9/2/06 Recent Posts

Likely the choice of repo.  The liferay workspace points at Liferay's repo where they release snapshot versions.  I think gradle would consistently pick the right version, all things being equal.