7.1 Target Platform Issue

Just a quick one this morning...

So I'm working on a project for 7.1. With my new love of the target platform, I decide I'm going to enable the 7.1 target platform for my DXP project.

Everything seems to work fine until I deploy the portlet jar. That's when I get the following during deployment:

2020-02-01 08:40:06.324 ERROR [fileinstall-/Users/dnebinger/liferay/71ee/bundle2/osgi/modules]
  [LogService:93] Error while starting bundle: 
    file:/Users/dnebinger/liferay/71ee/bundle2/osgi/modules/com.example.test.web-1.0.0.jar 
  org.osgi.framework.BundleException: 
    Could not resolve module: com.example.test.web [985]_  
    Unresolved requirement: Import-Package: javax.servlet; version="[3.1.0,4.0.0)"_ [Sanitized]
	at org.eclipse.osgi.container.Module.start(Module.java:444)
	at org.eclipse.osgi.internal.framework.EquinoxBundle.start(EquinoxBundle.java:428)
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundle(DirectoryWatcher.java:1275)
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.startBundles(DirectoryWatcher.java:1248)
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.doProcess(DirectoryWatcher.java:520)
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.process(DirectoryWatcher.java:365)
	at org.apache.felix.fileinstall.internal.DirectoryWatcher.run(DirectoryWatcher.java:316)

So my portlet bundle wouldn't deploy because the javax.servlet available was not 3.1.0 or greater and less than 4.0.0. I happen to know that, with 7.1, the servlet spec jar version included is 3.0.1, so I know it is definitely not available.

The question, of course, is why am I trying to use 3.1.0?

Hmm, I think, and go check the dependency line in the build.gradle file:

compile group: "javax.servlet", name: "javax.servlet-api"

Yep, that looks right...

Ah well, I think, I'll just override what the target platform is assigning:

compile group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"

I do a clean build and deploy, but still get the same error.

What the heck?

Long story short, it's actually the Liferay 3rd party BOM file. In that BOM, it declares that version 3.1.0 is provided, even though it isn't.

But this setting trumps everything, even the specific version that I want to use when I put it in the dependency line.

I was stuck on this, but found some help from Ray Auge. He, too, had hit this recently when trying to use a custom BOM for an organization (they want to manage their versions across multiple projects).

I adapted the solution he came up with. I built and deployed my module, and all was well.

Here's the fix:

dependencies {
    implementation enforcedPlatform(group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1")

    ...
    compile group: "javax.portlet", name: "portlet-api"
    compile group: "javax.servlet", name: "javax.servlet-api"
    compile group: "jstl", name: "jstl"
    ...
}

The magic line w/ the enforcedPlatform() is a Gradle thing. I honestly don't know a lot about it (I'm sure you Gradle-heads can fill us in).

But I do know that it forces resolution to stick with the exact dependency version I've listed, regardless of what any of the BOMs might say and even regardless of a version added on the dependency line itself.

So if you're using the 7.1 Target Platform and you get this weird servlet 3.1.0 unresolved requirement issue, sneak that line in at the top of your dependencies list and you'll be able to get it to work.

Enjoy!

Blogs

Hmm, just got this issue for 7.2 GA1, so it may not be limited to 7.1.  

But the same solution here worked in the 7.2 environ, so I'm good.

Another workaround would be to use "force = true". I found it easier to type and remember

 

compile(group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1") {force = true}

I have the same issue with Liferay 7.2 when using Maven. Any idea about how to fix it? 

I fixed this by adding the following lines in the bnd.bnd of the module and it works fine: 

-contract: JavaPortlet,JavaServlet

Thoughts? 

I've just run into the same problem on a DXP 7.1.10-ga1 (7.1.10.1 release from the Nexus Repository Manager, I guess).

When you say "I happen to know that, with 7.1, the servlet spec jar version included is 3.0.1", I wonder how you know that. In other words, how can I know what is the actual version of an specific artifact my current DXP instance is working with?

I'm asking that because when typing 'lb -s | grep javax.servlet' command on a Gogo shell, I get this result:

   16|Active     |    6|javax.servlet.jsp-api (2.3.2.b01)    17|Active     |    6|javax.servlet.jsp.jstl (1.2.3.LIFERAY-PATCHED-2)    18|Active     |    6|javax.servlet.jsp.jstl-api (1.2.1)  

From the results got, it doesn't seem the DXP server is providing the 'javax.servlet-api' artifact.

Looking forward to reading any reply from you. Thanks.