【问题标题】:Liferay service builder JNDI lookup uses the wrong naming contextLiferay 服务构建器 JNDI 查找使用了错误的命名上下文
【发布时间】:2015-04-01 18:26:17
【问题描述】:

我有一个通过 JNDI 配置的 servicebuilder portlet:

<Context antiJARLocking="true" useHttpOnly="true">
  <ResourceLink name="app/url" global="my-app/app/url"
    type="java.lang.String" />
</Context>

在我的ext-spring.xml 中,我尝试使用以下方法提取该值:

<jee:jndi-lookup jndi-name="java:comp/env/app/url" />

但是,用于查找此值的InitialContext 似乎是ROOT webapp(liferay 本身)的InitialContext,因为它包含的唯一内容是java:comp/env/jdbc/LiferayPool 数据库连接池。我知道 JNDI 上下文与ClassLoader 相关,由:

Thread.currentThread().getContextClassLoader();

而且我知道在运行 portlet 初始化之前 liferay 会与类加载器混为一谈。但对于我的一生,我无法弄清楚如何解决这个问题。有什么建议吗?

【问题讨论】:

    标签: spring tomcat jndi liferay-6 contextclassloader


    【解决方案1】:

    我为您提供了一个可行的解决方案,但它与您在帖子中描述的有点不同。

    首先,我建议你把JNDI的声明移到Tomcat的server.xml中,具体到标签中。

    这是一个例子:

    <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource
       name="jdbc/CustomDBPoolShared"
       auth="Container"
       type="javax.sql.DataSource"
       factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
       driverClassName="oracle.jdbc.OracleDriver"
       url="jdbc:oracle:thin:@YOUR_SERVER:1521:YOUR_SERVICE"
       username="USERNAME"
       password="PASSWORD"
       maxActive="20"
       maxIdle="5"
       maxWait="10000"
    />
    ......
    </GlobalNamingResources>
    

    之后,您应该在 context.xml 中创建一个 ResourceLink:

    <Context>
    
    <!-- Default set of monitored resources -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    
    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--
    <Manager pathname="" />
    -->
    
    <!-- Uncomment this to enable Comet connection tacking (provides events
         on session expiration as well as webapp lifecycle) -->
    <!--
    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
    -->
    <ResourceLink name="jdbc/CustomDBPool" global="jdbc/CustomDBPoolShared" type="javax.sql.DataSource"/>
    ....
    </Context>
    

    如果您有两个 portlet 访问同一个数据库,这将帮助您处理并发访问。

    最后是 ext-spring.xml:

       <!-- Custom Beans -->
    <bean id="digitalHibernateSessionFactory" class="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration" lazy-init="true">
        <property name="dataSource">
            <ref bean="customDBDataSource"/>
        </property>
    </bean>
    <bean id="customDBSessionFactory" class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl" lazy-init="true">
        <property name="sessionFactoryImplementor">
            <ref bean="digitalHibernateSessionFactory" />
        </property>
    </bean>
    <bean id="customDBDataSourceTarget" class="com.liferay.portal.spring.jndi.JndiObjectFactoryBean" lazy-init="true">
        <property name="jndiName">
            <value>jdbc/customDBPool</value>
        </property>
    </bean>
    <bean id="customDBDataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy" lazy-init="true">
        <property name="targetDataSource">
            <ref bean="customDBDataSourceTarget" />
        </property>
    </bean>
    

    注意 jdbc/customDBPool

    请注意 context.xml 中描述的 jdbc/customDBPool,它不仅适用于 ROOT 类加载器。

    最后,您应该像这样在 LiferayServiceBuilder 的 service.xml 中引用正确的数据源:

    <entity name="MyCustomEntity" table="CUSTOM_ENTITY" local-service="true" remote-service="false" data-source="customDBDataSource" session-factory="customDBSessionFactory" cache-enabled="false">
    .....
    </entity>
    

    【讨论】:

      猜你喜欢
      • 2012-07-13
      • 2016-06-04
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 2017-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多