Spring2.*提供了一个访问EJB的方法,即
“org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean”和
“org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean”
两个FactoryBean,一个用来访问本地的,一个用来访问远程的无状态SessionBean。但是这两个FactoryBean
只能针对EJB2.0的无状态SessionBean,所以在配置是必须提供SessionBean的Home接口。而在EJB3.0中已经没有了Home接口(或者说被隐藏起来了)。为了访问EJB3.0的无状态Session Bean就只好自己写一个了。
- package com.cyf.spring.ext;
- import javax.naming.Context;
- import javax.naming.InitialContext;
- import javax.naming.NamingException;
- import org.apache.log4j.Logger;
- import org.springframework.beans.factory.FactoryBean;
- import org.springframework.jndi.JndiTemplate;
- public class SlsbFactoryBean implements FactoryBean {
- private static Logger log=Logger.getLogger(SlsbFactoryBean.class);
- private JndiTemplate jndiTemplate;
- private Context ejbCtx;
- private String jndiName;
- private Object ejbobj;
- public synchronized Object getEjbObject(){
- if (ejbobj==null){
- if (jndiTemplate == null || jndiTemplate.getEnvironment() == null) {
- throw new LookupSlsbException("jndiTemplate is required!");
- }
- try {
- ejbCtx = new InitialContext(jndiTemplate.getEnvironment());
- } catch (Exception e) {
- throw new LookupSlsbException(
- "can't initial a javax.naming.InitialContext ");
- }
- if (jndiName==null){
- throw new LookupSlsbException("jndiName is required!");
- }
- try {
- ejbobj=ejbCtx.lookup(jndiName);
- return ejbobj;
- } catch (NamingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
- }
- }else{
- return ejbobj;
- }
- }
- public Object getObject() throws Exception {
- // TODO Auto-generated method stub
- return getEjbObject();
- }
- public Class getObjectType() {
- // TODO Auto-generated method stub
- return null;
- }
- public boolean isSingleton() {
- // TODO Auto-generated method stub
- return false;
- }
- public JndiTemplate getJndiTemplate() {
- return jndiTemplate;
- }
- public void setJndiTemplate(JndiTemplate jndiTemplate) {
- log.info("setting jndiTemplate....");
- this.jndiTemplate = jndiTemplate;
- }
- public String getJndiName() {
- return jndiName;
- }
- public void setJndiName(String jndiName) {
- log.info("setting jndiName");
- this.jndiName = jndiName;
- }
- }
这个类实现了Spring的FactoryBean接口
- /*
- * Copyright 2002-2007 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.springframework.beans.factory;
- /**
- * Interface to be implemented by objects used within a {@link BeanFactory}
- * which are themselves factories. If a bean implements this interface,
- * it is used as a factory for an object to expose, not directly as a bean
- * instance that will be exposed itself.
- *
- * <p><b>NB: A bean that implements this interface cannot be used as a
- * normal bean.</b> A FactoryBean is defined in a bean style, but the
- * object exposed for bean references is always the object that it creates.
- *
- * <p>FactoryBeans can support singletons and prototypes, and can
- * either create objects lazily on demand or eagerly on startup.
- *
- * <p>This interface is heavily used within the framework itself, for
- * example for the AOP {@link org.springframework.aop.framework.ProxyFactoryBean}
- * or the {@link org.springframework.jndi.JndiObjectFactoryBean}.
- * It can be used for application components as well; however,
- * this is not common outside of infrastructure code.
- *
- * @author Rod Johnson
- * @author Juergen Hoeller
- * @since 08.03.2003
- * @see org.springframework.beans.factory.BeanFactory
- * @see org.springframework.aop.framework.ProxyFactoryBean
- * @see org.springframework.jndi.JndiObjectFactoryBean
- */
- public interface FactoryBean {
- Object getObject() throws Exception;
- Class getObjectType();
- boolean isSingleton();
- }
请注意FactoryBean的“getObject()”方法,这个方法将会在Spring客户端调用ApplicationContext.getBean()的时候被调用,或者说getObject()代理了getBean()方法,下面将会看一个例子。所以我在getObject()方法中去lookup EJB3.0的sessionbean。
再来看下Spring配置文件。
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
- <bean id="propertyConfigurer"
- class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="location">
- <value>WEB-INF/classes/jndi.properties</value>
- </property>
- </bean>
- <bean id="jndiTemplate"
- class="org.springframework.jndi.JndiTemplate">
- <property name="environment">
- <props>
- <prop key="java.naming.provider.url">
- ${java.naming.provider.url}
- </prop>
- <prop key="java.naming.factory.initial">
- ${java.naming.factory.initial}
- </prop>
- <prop key="java.naming.factory.url.pkgs">
- ${java.naming.factory.url.pkgs}
- </prop>
- </props>
- </property>
- </bean>
- <bean id="RemoteDAO" class="com.cyf.spring.ext.SlsbFactoryBean">
- <property name="jndiTemplate">
- <ref local="jndiTemplate" />
- </property>
- <property name="jndiName" value="CommonDAOImpl/remote" />
- </bean>
- </beans>
SlsbFactoryBean只需要设置jndi属性模板和jndiName,不需要EJB2.0的home接口了
调用的例子:
- package com.cyf.spring.ext;
- import java.util.List;
- import javax.faces.context.FacesContext;
- import org.apache.log4j.Logger;
- import org.springframework.context.ApplicationContext;
- import org.springframework.web.jsf.FacesContextUtils;
- import com.book.business.CommonDAO;
- import com.bookstore.admin.actions.PressAction;
- public class TestSlsbFactoryBean {
- //在JSF环境中得到SpringApplicationContext
- private static ApplicationContext ctx = FacesContextUtils
- .getWebApplicationContext(FacesContext.getCurrentInstance());
- private static Logger log = Logger.getLogger(TestSlsbFactoryBean.class);
- public void testBean() {
- //getBean(RemoteDAO)返回的结果就是调用SlsbFactoryBean.getObject()方法返回的结果
- CommonDAO dao = (CommonDAO)ctx.getBean("RemoteDAO");
- List list = dao.getObjByEQL("select count(p) from Press p", null, -1, -1);
- long size = (Long) list.get(0);
- log.info(size);
- }
- }