Liferay 6 使用 Common Service Builder 层错误 - BeanLocatorException - BeanLocator 尚未设置

发布于 2024-11-14 22:21:05 字数 2325 浏览 4 评论 0原文

我们正在尝试使用 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 开发。

We are trying to use liferay service builder as a common layer for all our portlets. We have created a separate common portlet project where we are building the service using service.xml This generates a service.jar file for us. We are copying this jar to all portlets WEB-INF/lib dir.

When we run the portlet it throws following error on the logs and Portlet is temporarily unavailable message is displayed on the 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)

I am sure that this approach should work seamlessly. But found several people complaining about it on liferay forums, but did not find any solution yet. Please let us know if you found a way to use service builder as a common layer and it worked for you.

We are using maven for building all portlet projects.

Liferay Version is 6.0.5
And we are using Spring Portlet MVC for our portlet development.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

眼前雾蒙蒙 2024-11-21 22:21:06

我在做 Maven portlet 时遇到了类似的问题。
首先我创建了 portlet,然后放入了 service.xml

问题是生成器正在寻找不存在的 portlet 名称
我解决了明确Portlet名称的问题,我希望生成器特别寻找

,为此,两个pom节点必须相等

project.artifatctId =(liferay为此创建一个bean定位器)

project.build.(liferay插件).configuration .pluginName = 生成器的 portlet 的内部名称

作为示例,摘自我的 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 和 TWo 必须相同

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

微暖i 2024-11-21 22:21:06

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

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

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

Problem with BeenLocator with my spring portlet for me was
that my portlet's spring context was getting initialized before liferay's spring context did.

I was using
ClassName className = ClassNameLocalServiceUtil.getClassName(JournalArticle.class.getName()); in my constructor. LIferay's context was not loaded hence the error. I moved that piece of code to be called when (only that time) first request needed it. Problem was solved.

So do not depend on lifery during initialization of your portlet, do some kind of "lazy" wiring of dependencies to liferay.

篱下浅笙歌 2024-11-21 22:21:06

由于您使用的是 Maven,请尝试确保您的 war 名称等于您的 portlet 项目名称。
调试后,我发现 ClpSerializer 定义了 _servletContextName ,它等于 war 项目的 。如果您部署名为 artifactId-1.0.0-snapshot.war 的工件,则会使用该名称创建上下文,但 servicegen 生成的代码期望它是 artifactId。使用您的 ClpSerializer 进行验证。

Since you are using maven, try to make sure your war name equals to your portlet project name.
After debug i've found that ClpSerializer defines _servletContextName which is equal to <artifactId> of war project. If you deploy artifact named artifactId-1.0.0-snapshot.war the context will be created with that name, but code, generated by servicegen expects it to be artifactId. Verify with your ClpSerializer.

眼眸 2024-11-21 22:21:06

我也有同样的问题。我将以下代码放置在 portlet 的 liferay-plugin-package.properties 文件中,该文件使用公共 portlet 的服务层。这对我有用。

required-deployment-contexts=common-portlet

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

I also had the same problem. I placed the following code in liferay-plugin-package.properties file of portlets which uses the service layer of common portlet. It worked for me.

required-deployment-contexts=common-portlet

It's better to copy the service.jar file to tomcat/lib/ext instead of all portlets WEB-INF/lib.

┊风居住的梦幻卍 2024-11-21 22:21:06

我执行了以下操作来解决上述问题:

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

    <前><代码> <插件>
    com.liferay.maven.plugins
    liferay-maven-plugin;
    <版本>${liferay.version}
    <配置>
    ${liferay.auto.deploy.dir}
    ${liferay.app.server.portal.dir}${liferay.version}portlet<插件名称>XXXX-portlet

  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)) {
返回_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. 部署战争,验证战争名称和日志中的上下文名称是否正确

I did the following to solve the above problem:

  1. Set the plugin config property pluginName in pom.xml to the correct context

        <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. Optionally set the XXXX-portlet-deployment-context property in liferay plugin properties file or portlet.properties file

XXXX-portlet-deployment-context=XXXX-portlet

  1. Re-Build the services
  2. Verify if the generated ClpSerializer.java contains the correct contexts

` 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. Deploy the war, verify the war name and the logs for the correct context name.
醉梦枕江山 2024-11-21 22:21:05

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

required-deployment-contexts=[Portlet-Hook name]

You have to build-service AND deploy the (Portlet-Hook) that is required for your current portlet, you can know it by see its name in liferay-plugin-package.properties file as:

required-deployment-contexts=[Portlet-Hook name]
游魂 2024-11-21 22:21:05

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

到 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

version = 1.0

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

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

com.liferay.portal.kernel.bean.PortletBeanLocatorUtil

,其中

BeanLocator beanLocator = getBeanLocator(servletContextName);

调用的位置总是返回 null 而没有版本号...

我希望有人能提供帮助。

I tryed anything written on that page, but nothing worked for me, until i added the project's version

to maven-pluginname in pom:

            <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>

and in liferay-plugin-package.properties:

   artifactId-version-deployment-context=artifactId-version

for example:

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

where artifactId = portlet-sample

and version = 1.0

After all I i built services, and redeployed my war.

I came to the solution because I debugged:

com.liferay.portal.kernel.bean.PortletBeanLocatorUtil

where

BeanLocator beanLocator = getBeanLocator(servletContextName);

is called which always returned null without versionnumber...

I hope someone helps this.

风和你 2024-11-21 22:21:05

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

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

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

I had a hard time finding a solution to this error so I will post what we did. The name of the portlet changed, built the service and when running the portlet throws the same error:

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

In our case we had to remove the jar file from ../docroot/WEB-INF/lib/portlet-service.jar

一江春梦 2024-11-21 22:21:05

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

因此,我们生成的 sourceportlet-service.jar 从 Source-portlet 的 WEB-INF/lib 移动到 < code>{tomcat_home}/lib/ext 文件夹是其他 jar 文件,例如 portlet-service.jar 等。

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

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

希望这会有所帮助。

We had a requirement to use something similar: Have a portlet (lets say Source-portlet) whose services will be used by other portlets.

So we moved the generated sourceportlet-service.jar from the Source-portlet's WEB-INF/lib to {tomcat_home}/lib/ext folder were other jars like portlet-service.jar etc reside.

The down side of this approach is whenever there is a change in the Source-portlet we would need to restart the server.

If the other portlet's are your custom plugin portlets than another approach would be to copy the generated sourceportlet-service.jar to other portlet's WEB-INF/lib. This approach does not work if you are using the service in a JSP hook.

Hope this would help.

凡间太子 2024-11-21 22:21:05

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

如果它们这样做,则根据您的应用程序服务器实例化您的 web 应用程序的顺序(并且在 Tomcat 中您无法指定启动顺序),每次 portlet web 应用程序在构建器 web 应用程序之前部署时,都会发生 BeanLocatorException。

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

The previous answer by Martin Gamulin is correct. If you have two separate web apps, one for Spring portlets and another with your Service Builder (which seems to be the correct way to do things in Liferay), then you need to ensure that your Spring portlets do not reference your ServiceBuilder classes during initialization.

If they do then depending on the order in which your app server instantiates your webapps (and in Tomcat you can't specify a startup order), the BeanLocatorException will happen every time the portlets webapp deploys before the builder webapp.

In our case this meant moving a XxxLocalServiceUtil.createXxx(0) call from the constructor of the portlet Controller to the relevant methods.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文