Custom taglib not loaded with Liferay7
Asked Answered
R

2

8

I am migrating my Liferay portlets from 6.0 to Liferay 7.0 and one of the many roadblocks that I am hitting is the inclusion of my custom taglib.

I followed the advice from: Creating a custom taglib in Liferay 7 but my portlet fails to load the taglib, the following error is logged:

09:50:48,566 ERROR [http-nio-8080-exec-10][FreeMarkerManager:208] Unable to add taglib my_tags to context
FreeMarker template error:
freemarker.template.TemplateModelException: Error while loading tag library for URI "/META-INF/my_tags.tld" from TLD location "servletContext:/META-INF/my_tags.tld"; see cause exception.
        at freemarker.ext.jsp.TaglibFactory.get(TaglibFactory.java:260)
        at com.liferay.portal.template.freemarker.internal.FreeMarkerManager$TaglibFactoryWrapper.get(FreeMarkerManager.java:647)
        at com.liferay.portal.template.freemarker.internal.FreeMarkerManager.addTaglibSupport(FreeMarkerManager.java:205)
        at com.liferay.taglib.util.ThemeUtil.doIncludeFTL(ThemeUtil.java:276)
        at com.liferay.taglib.util.ThemeUtil.doDispatch(ThemeUtil.java:157)
        at com.liferay.taglib.util.ThemeUtil.includeFTL(ThemeUtil.java:100)
        at com.liferay.taglib.util.ThemeUtil.include(ThemeUtil.java:82)

However, my bundle JAR does contain META-INF/my_tags.tld

What strikes me, is that the error does not happen when my JSP is loaded but somewhere inside the theme's FreeMarker template. Apparently my JSP isn't even loaded at that point.

The error is thrown on each page in my portal, not only those that contain my portlet(s) (which is to be expected if the theme is already failing to access the taglib)

The structure of the bundle JAR is:

com/
content/  
META-INF/
   +--- resources/
   MANIFEST.MF
   taglib-mappings.properties
   my_tags.tld
OSGI-INF/
WEB-INF/         

The MANIFEST.MF that is generated by the bnd task contains the following dependency:

Require-Capability: osgi.extender;osgi.extender="jsp.taglib";uri="/META-INF/my_tags.tld"

The file taglib-mappings.properties contains:

my_tags=/META-INF/my_tags.tld 

I also tried putting the .tld files into WEB-INF/tld where it would be with a plain, simple, standard portlet or web application, but to no avail either.

Do I need to add a mapping in the web.xml (I am not sure if the new OSGi portlets even use web.xml) or add some other configuration option?

Rovit answered 28/6, 2017 at 8:10 Comment(0)
R
6

OK, I managed to figure this out by myself.

The directory layout needs to be like this:

+---java
|   \---com
|       \---mypackage
|           |   
|           +---portlet
|           |       MyPortlet.java
|           |       
|           \---tags
|                   LabelTag.java
|                   
\---resources
    +---content
    |       Language.properties
    |       
    +---META-INF
    |   |   my_tags.tld
    |   |   
    |   \---resources
    |       |   view.jsp
    |               
    \---WEB-INF

In contrast to some hints on the internet, the file taglib-mappings.properties is not needed. If it is present, Liferay throws a gazillion of exceptions because the Freemarker engine tries to access the taglibs that are referenced in taglib-mappings.properties.

And my_tags.tld contains the following:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
  <tlib-version>1.0</tlib-version>
  <jsp-version>1.1</jsp-version>
  <short-name>ka</short-name>
  <uri>http://example.com/tld/my_tags</uri>

  <tag>
    <name>label</name>
    <tag-class>com.mypackage.tags.LabelTag</tag-class>
    <body-content>scriptless</body-content>
    <attribute>
      <name>labelText</name>
      <required>true</required>
      <rtexprvalue>true</rtexprvalue>
      <type>java.lang.String</type>
    </attribute>
  </tag>
</taglib>

The in the JSP page, the tag is defined as:

<%@ taglib uri="http://example.com/tld/my_tags" prefix="my" %>

I do not include a Require-Capability: for my own tags in the OSGI MANIFEST.MF file.

I only include that for the standard JSTL and Liferay tags:

Require-Capability: osgi.extender;filter:="(&(osgi.extender=jsp.taglib)(
 uri=http://java.sun.com/portlet_2_0))",osgi.extender;filter:="(&(osgi.e
 xtender=jsp.taglib)(uri=http://liferay.com/tld/aui))",osgi.extender;fil
 ter:="(&(osgi.extender=jsp.taglib)(uri=http://liferay.com/tld/portlet))
 ",osgi.extender;filter:="(&(osgi.extender=jsp.taglib)(uri=http://lifera
 y.com/tld/theme))",osgi.extender;filter:="(&(osgi.extender=jsp.taglib)(
 uri=http://liferay.com/tld/ui))",osgi.ee;filter:="(&(osgi.ee=JavaSE)(ve
 rsion=1.8))"

However, I did need to exclude some packages in the OSGI bnd.bnd file that were included due to the dependency on javax.servlet.jsp and jstl

Import-Package: \
    .....
    !com.ibm.*,\
    !com.sun.*,\
    !javax.jmdns.*,\
    * 
Rovit answered 6/7, 2017 at 10:20 Comment(0)
U
0

I had the same problem, and found a solution: just add, in your "liferay-plugin-package.properties" file

Provide-Capability=osgi.extender;osgi.extender="jsp.taglib";uri="/META-INF/my-tags.tld"

Note that you may also keep your tld file in "/WEB-INF/tld" - and change from "/META-INF" to "/WEB-INF/tld" in your configuration files.

Unclasp answered 13/11, 2019 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.