Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom taglib not loaded with Liferay7

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?

like image 237
a_horse_with_no_name Avatar asked Jun 28 '17 08:06

a_horse_with_no_name


1 Answers

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.*,\
    * 
like image 122
a_horse_with_no_name Avatar answered Oct 18 '22 01:10

a_horse_with_no_name