10

我们正在尝试使用 liferay 服务构建器作为我们所有 portlet 的公共层。我们创建了一个单独的通用 portlet 项目,我们在其中使用 service.xml 构建服务。这将为我们生成一个 service.jar 文件。我们将此 jar 复制到所有 portlet WEB-INF/lib 目录。

当我们运行 portlet 时,它会在日志中引发以下错误,并且 portlet 暂时不可用消息显示在 portlet 上。

14:43:17,447 ERROR [jsp:154] com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set
    at com.liferay.portal.kernel.bean.PortletBeanLocatorUtil.locate(PortletBeanLocatorUtil.java:40)
    at com.cogs.common.service.CourseLocalServiceUtil.getService(CourseLocalServiceUtil.java:223)
    at com.cogs.common.service.CourseLocalServiceUtil.getCoursesCount(CourseLocalServiceUtil.java:187)
    at org.apache.jsp.jsps.course.course_005fview_jsp._jspService(course_005fview_jsp.java:542)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
    at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:551)
    at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:488)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)

我确信这种方法应该可以无缝地工作。但是在liferay论坛上发现有几个人在抱怨它,但还没有找到任何解决方案。如果您找到了将服务构建器用作公共层的方法并且对您有用,请告诉我们。

我们使用 maven 来构建所有的 portlet 项目。

Liferay 版本是 6.0.5 我们正在使用 Spring Portlet MVC 进行 portlet 开发。

4

10 回答 10

3

您必须构建服务并部署当前 portlet 所需的 (Portlet-Hook),您可以通过在 liferay-plugin-package.properties 文件中查看其名称来了解它:

required-deployment-contexts=[Portlet-Hook name]
于 2013-12-11T13:47:18.557 回答
3

我尝试了该页面上写的任何内容,但没有任何效果,直到我添加了项目的版本

pom 中的 maven-pluginname

            <configuration>
                <autoDeployDir>${liferay.auto.deploy.dir}</autoDeployDir>
                <appServerDeployDir>${liferay.app.server.deploy.dir}</appServerDeployDir>
                <appServerLibGlobalDir>${liferay.app.server.lib.global.dir}</appServerLibGlobalDir>
                <appServerPortalDir>${liferay.app.server.portal.dir}</appServerPortalDir>
                <liferayVersion>${liferay.version}</liferayVersion>
                <pluginType>portlet</pluginType>
                <pluginName>${project.artifactId}-${project.version}</pluginName>
            </configuration>

liferay-plugin-package.properties中:

   artifactId-version-deployment-context=artifactId-version

例如:

   portlet-sample-1.0-deployment-context=portlet-sample-1.0

其中artifactId = portlet-sample

版本= 1.0

毕竟我建立了服务,并重新部署了我的战争。

我来到解决方案是因为我调试了:

com.liferay.portal.kernel.bean.PortletBeanLocatorUtil

在哪里

BeanLocator beanLocator = getBeanLocator(servletContextName);

调用它总是返回 null 而没有版本号...

我希望有人对此有所帮助。

于 2016-01-19T11:53:06.530 回答
2

我们需要使用类似的东西:有一个 portlet(比如说Source-portlet),它的服务将被其他 portlet 使用。

因此,我们生成sourceportlet-service.jar的从 Source-portlet 的文件夹WEB-INF/lib移到{tomcat_home}/lib/ext其他 jarportlet-service.jar等驻留的文件夹中。

这种方法的缺点是,只要 Source-portlet 发生变化,我们就需要重新启动服务器。

如果其他 portlet 是您的自定义插件 portlet,那么另一种方法是将生成的 portlet 复制sourceportlet-service.jar到其他 portlet 的WEB-INF/lib. 如果您在 JSP 挂钩中使用该服务,则此方法不起作用。

希望这会有所帮助。

于 2012-03-14T10:52:13.447 回答
2

我很难找到解决这个错误的方法,所以我会发布我们所做的。更改了 portlet 的名称,构建了服务,并且在运行 portlet 时会引发相同的错误:

com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set for servlet context

在我们的例子中,我们必须从 ../docroot/WEB-INF/lib/portlet-service.jar 中删除 jar 文件

于 2012-01-16T11:36:14.150 回答
1

I had a a similar problem doing a maven portlet. First i did the portlet and then i put the service.xml

The issue was that the generator was looking for a portlet name that was not there i solved making expliciting the portlet name i wanteed the genrator to look for

in particular, to do this two pom nodes must be equal

project.artifatctId = (liferay creates a bean locator for this)

and

project.build.(liferay plugin).configuration.pluginName = the internal name of the portlet for the generator

as an example, a small exerpt from my pom.xml

<modelVersion>4.0.0</modelVersion>
<groupId>io.endeios</groupId>
<artifactId>ShowTheCats-portlet</artifactId><!-- ONE -->
<packaging>war</packaging>
<name>ShowTheCats Portlet</name>
<version>1.0-SNAPSHOT</version>
<build>
    <plugins>
        <plugin>
            <groupId>com.liferay.maven.plugins</groupId>
            <artifactId>liferay-maven-plugin</artifactId>
            <version>${liferay.maven.plugin.version}</version>
            <executions>
                <execution>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>build-css</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <autoDeployDir>${liferay.auto.deploy.dir}</autoDeployDir>
                <appServerDeployDir>${liferay.app.server.deploy.dir}</appServerDeployDir>
                <appServerLibGlobalDir>${liferay.app.server.lib.global.dir}</appServerLibGlobalDir>
                <appServerPortalDir>${liferay.app.server.portal.dir}</appServerPortalDir>
                <liferayVersion>${liferay.version}</liferayVersion>
                <pluginType>portlet</pluginType>
                <pluginName>ShowTheCats-portlet</pluginName><!-- TWO -->
            </configuration>
        </plugin>

ONE and TWo must be the same

于 2014-10-24T17:27:44.507 回答
1

Martin Gamulin 之前的回答是正确的。如果您有两个单独的 Web 应用程序,一个用于 Spring portlet,另一个用于您的 Service Builder(这似乎是在 Liferay 中做事的正确方法),那么您需要确保您的 Spring portlet 在初始化期间不引用您的 ServiceBuilder 类.

如果他们这样做,则取决于您的应用程序服务器实例化您的 webapps 的顺序(并且在 Tomcat 中您不能指定启动顺序),每次 portlets webapp 在构建器 webapp 之前部署时都会发生 BeanLocatorException。

在我们的例子中,这意味着将XxxLocalServiceUtil.createXxx(0)调用从 portlet Controller 的构造函数转移到相关方法。

于 2011-11-24T16:47:30.707 回答
0

我也有同样的问题。我将下面的代码放在了portlet 的liferay-plugin-package.properties 文件中,该文件使用了通用portlet 的服务层。它对我有用。

required-deployment-contexts=common-portlet

最好将 service.jar 文件复制到 tomcat/lib/ext 而不是所有 portlet WEB-INF/lib。

于 2013-10-10T05:53:17.937 回答
0

由于您使用的是 maven,因此请尝试确保您的战争名称等于您的 portlet 项目名称。调试后我发现它ClpSerializer定义了_servletContextName等于<artifactId>战争项目。如果您部署名为artifactId-1.0.0-snapshot.war的工件,则将使用该名称创建上下文,但 servicegen 生成的代码期望它是artifactId. 与您的ClpSerializer.

于 2013-05-30T10:23:13.773 回答
0

对我来说,BeenLocator 与我的 spring portlet 的问题是我的 portlet 的 spring 上下文在 liferay 的 spring 上下文之前被初始化。

ClassName className = ClassNameLocalServiceUtil.getClassName(JournalArticle.class.getName());在我的构造函数中使用。LIferay 的上下文未加载,因此出现错误。我移动了那段代码,以便在(仅在那个时候)第一次请求需要它时调用它。问题解决了。

因此,在您的 portlet 初始化期间不要依赖 lifery,对 liferay 进行某种“懒惰”的依赖连接。

于 2011-11-18T08:54:03.633 回答
0

我做了以下来解决上述问题:

  1. 将 pom.xml 中的插件配置属性 pluginName 设置为正确的上下文

        <plugin>
            <groupId>com.liferay.maven.plugins</groupId>
            <artifactId>liferay-maven-plugin</artifactId>
            <version>${liferay.version}</version>
            <configuration>
                <autoDeployDir>${liferay.auto.deploy.dir}</autoDeployDir>
                <appServerPortalDir>${liferay.app.server.portal.dir}</appServerPortalDir>
                <liferayVersion>${liferay.version}</liferayVersion>
                <pluginType>portlet</pluginType>
                <pluginName>XXXX-portlet</pluginName>
            </configuration>
        </plugin>
    
  2. 可选择在 liferay 插件属性文件或 portlet.properties 文件中设置 XXXX-portlet-deployment-context 属性

XXXX-portlet-deployment-context=XXXX-portlet

  1. 重新构建服务
  2. 验证生成的 ClpSerializer.java 是否包含正确的上下文

` public static String getServletContextName() { if (Validator.isNotNull(_servletContextName)) { return _servletContextName; }

    synchronized (ClpSerializer.class) {
        if (Validator.isNotNull(_servletContextName)) {
            return _servletContextName;
        }

        try {
            ClassLoader classLoader = ClpSerializer.class.getClassLoader();

            Class<?> portletPropsClass = classLoader.loadClass(
                    "com.liferay.util.portlet.PortletProps");

            Method getMethod = portletPropsClass.getMethod("get",
                    new Class<?>[] { String.class });

            String portletPropsServletContextName = (String) getMethod.invoke(null,
                    "XXXX-portlet-deployment-context");

            if (Validator.isNotNull(portletPropsServletContextName)) {
                _servletContextName = portletPropsServletContextName;
            }
        } catch (Throwable t) {
            if (_log.isInfoEnabled()) {
                _log.info(
                    "Unable to locate deployment context from portlet properties");
            }
        }

        if (Validator.isNull(_servletContextName)) {
            try {
                String propsUtilServletContextName = PropsUtil.get(
                        "XXXX-portlet-deployment-context");

                if (Validator.isNotNull(propsUtilServletContextName)) {
                    _servletContextName = propsUtilServletContextName;
                }
            } catch (Throwable t) {
                if (_log.isInfoEnabled()) {
                    _log.info(
                        "Unable to locate deployment context from portal properties");
                }
            }
        }

        if (Validator.isNull(_servletContextName)) {
            _servletContextName = "upay-portlet";
        }

        return _servletContextName;
    }
}`
  1. 部署战争,验证战争名称和正确上下文名称的日志。
于 2015-10-26T10:51:10.230 回答