请注意,到目前为止所讨论的全部内容都完全符合 CMP 2.x Bean 的 EJB 规范;即,任何符合规范的可移植 CMP Bean
都可以使用 IBM 工具和运行时保存到任意非关系数据存储中。不过,WebSphere Process Server
还支持称为“数据逻辑”的特定于 IBM 的 J2EE 编程模型扩展,此扩展实质上允许开发人员将在 CMP Bean
实现类上定义的任意方法的实现推迟到部署时进行。此类方法在 CMP Bean 实现类上声明为抽象方法,可以“向下推”到
UDPDMI,由部署人员进行实现,以与后端数据存储交互,例如调用以更成熟的方式与数据交互的某个遗留事务,而不采用简单的 CMP
生命周期方法。这样,就可以通过 J2EE 编程模型将现有遗留应用程序向用户公开,而不会将此类应用程序限制为采用基本 CRUD
方式与遗留数据进行交互。有关使用 CRUD 方法和数据逻辑方法的详细信息,请参阅使用场景部分。
IBM 在 WebSphere Business Integration-Server Foundation Version 5.1
产品及其相关的 WebSphere Studio Application Developer Integration Edition
Version 5.1 中首次引入 CMP/A。在该版本中,CMP/A 更多地是注重直接从 UDPDMI 访问后端数据存储,如通过直接使用
JDBC 或 JCA 进行访问。当然,在 WebSphere Process Server Version 6.0
中仍然支持此功能,但更注重通过中间 SOA 层间接访问此类数据存储。这样,CMP Bean
部署人员就不需要了解与后端数据存储交互的底层细节,而只需要了解如何调用服务上的可用操作即可,可以转而让服务实现人员来确定如何与后端数据存储进行最
好的交互。实现 SOA 访问的首选方法是通过在该产品的 6.0 版中引入的服务组件体系结构 (SCA) 进行。还应该注意,WebSphere
Business Integration Server Foundation Version 5.1 仅支持采用 EJB 2.0 Bean 的
CMP/A,而 WebSphere Process Server Version 6.0 同时支持采用 EJB 2.0 和 EJB 2.1
Bean 的 CMP/A。
JAX-RPC:JAX-RPC
后端类型用于将 CMP Bean 保存到提供可通过 Java API for XML Remote Procedure Calls
(JAX-RPC) 访问的 SOA 接口的后端系统。对于此后端类型,UDPDMI 的每个方法均包含用于查找 Web 服务和对其调用操作(通过
DII)的代码。在与填充向 Web
服务操作传递的输入对象数组、处理任何返回值及任何必要的异常处理相关的位置,需要客户对生成的代码进行插入或修改。请注意,6.0
版本通过添加对复杂类型和错误的改进支持改善了 JAX-RPC 支持。
/** * User-defined push-down method ejbCreate. * If the bean already exists in the backend datastore, then you should * throw a javax.ejb.DuplicateKeyException. * * @param bean Reference to the bean implementation class * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @exception javax.ejb.CreateException Thrown if an exception occurs creating bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. **/ public void ejbCreate( AccountBean bean, AccessIntent accessIntent, Object connection) throws javax.ejb.CreateException, ResourceException { log.entering("AccountBeanUserDefinedPushDownMethodsImpl", "ejbCreate(AccountBean, AccessIntent, Object)", new Object[] {bean, accessIntent, connection}); //The following code uses the JAX-RPC Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) JAX-RPC //stubs (produced by a tool such as wscompile or WSDL2Java) if desired. if (service == null) init(); javax.ejb.DuplicateKeyException dupKey = null; try { javax.xml.namespace.QName operation = new javax.xml.namespace.QName("createAccount"); // Change line below if operation returns a response (that is, if it is non-void) // For example, if it returns a float, then set returnType as follows: // returnType = new QName("http://www.w3.org/2001/XMLSchema", "float"); javax.xml.namespace.QName returnType = new javax.xml.namespace.QName( "http://www.w3.org/2001/XMLSchema", "boolean"); int paramCount = 2; //change to actual param count Object[] params = new Object[paramCount]; // Begin customer-written code to populate params array params[0] = bean.getId(); params[1] = new Float(bean.getBalance()); // End customer-written code to populate params array Object result = helper.invokeJAXRPCCall( service, port, operation, returnType, endpointAddress, params); boolean success = ((Boolean) result).booleanValue(); if (!success) dupKey = new javax.ejb.DuplicateKeyException(bean.getId().toString()); } catch (ResourceException re) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbCreate(AccountBean, AccessIntent, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbCreate(AccountBean, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (dupKey != null) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbCreate(AccountBean, AccessIntent, Object)", dupKey); throw dupKey; } log.exiting("AccountBeanUserDefinedPushDownMethodsImpl", "ejbCreate(AccountBean, AccessIntent, Object)"); }
/** * User-defined push-down method ejbFindByPrimaryKey. * For single object finders, if the bean does not exist in the backend * datastore, then you should throw a javax.ejb.ObjectNotFoundException. * For multi-object finders, if no results are found in the backend * datastore, then you should return an empty Record. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @return The return type of this finder method is a Record of Records, * each inner record of which contains the values of the bean's CMP fields, * with primitives wrapped (such as a java.lang.Integer for an int). * Note that with single-bean finders, like ejbFindByPrimaryKey, the outer * record will contain exactly one inner record, whereas with multi-bean * finders the outer record will contain zero or more inner records. The * order of the fields of the inner record must be as follows: * Position #0: id * Position #1: balance * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindByPrimaryKey( java.lang.Integer arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { log.entering("AccountBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); //The following code uses the JAX-RPC Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) JAX-RPC //stubs (produced by a tool such as wscompile or WSDL2Java) if desired. if (service == null) init(); javax.ejb.ObjectNotFoundException notFound = null; IndexedRecord returnValue = helper.createCCIIndexedRecord(); try { javax.xml.namespace.QName operation = new javax.xml.namespace.QName("retrieveAccount"); // Change line below if operation returns a response (that is, if it is non-void) // For example, if it returns a float, then set returnType as follows: // returnType = new QName("http://www.w3.org/2001/XMLSchema", "float"); javax.xml.namespace.QName returnType = new javax.xml.namespace.QName( "http://www.w3.org/2001/XMLSchema", "float"); int paramCount = 1; //change to actual param count Object[] params = new Object[paramCount]; // Begin customer-written code to populate params array params[0] = arg0; // End customer-written code to populate params array Object result = helper.invokeJAXRPCCall( service, port, operation, returnType, endpointAddress, params); // Add records to returnValue record as described in this method's JavaDoc if (result == null) { notFound = new javax.ejb.ObjectNotFoundException(arg0.toString()); } else { IndexedRecord account = helper.createCCIIndexedRecord(); account.add(0, arg0); //id account.add(1, result); //balance returnValue.add(0, arg0); //single object finder } } catch (ResourceException re) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (notFound != null) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", notFound); throw notFound; } log.exiting("AccountBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", returnValue); return returnValue; }
/** * User-defined push-down method ejbStore. * If the bean no longer exists in the backend datastore, then you should * throw a javax.ejb.NoSuchEntityException. * * @param bean Reference to the bean implementation class, containing the "new" field values * @param accessIntent Reference to the access intent settings to be used for this method * @param oldValues IndexedRecord holding original values of CMP fields. If * the accessIntent indicates that optimistic concurrency control is being * used, then this holds the values of the CMP fields as they were when the * bean was loaded. If the values have changed since then in the backend * datastore, then you should throw a javax.ejb.NoSuchEntityException. * The order of the CMP fields in the IndexedRecord is as follows: * Position #0: id * Position #1: balance * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @exception javax.ejb.NoSuchEntityException Thrown if bean no longer exists * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public void ejbStore( AccountBean bean, AccessIntent accessIntent, IndexedRecord oldValues, Object connection) throws javax.ejb.NoSuchEntityException, ResourceException { log.entering("AccountBeanUserDefinedPushDownMethodsImpl", "ejbStore(AccountBean, AccessIntent, IndexedRecord, Object)", new Object[] {bean, accessIntent, oldValues, connection}); //The following code uses the JAX-RPC Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) JAX-RPC //stubs (produced by a tool such as wscompile or WSDL2Java) if desired. if (service == null) init(); javax.ejb.NoSuchEntityException noSuchEntity = null; try { javax.xml.namespace.QName operation = new javax.xml.namespace.QName("updateAccount"); // Change line below if operation returns a response (that is, if it is non-void) // For example, if it returns a float, then set returnType as follows: // returnType = new QName("http://www.w3.org/2001/XMLSchema", "float"); javax.xml.namespace.QName returnType = new javax.xml.namespace.QName( "http://www.w3.org/2001/XMLSchema", "boolean"); int paramCount = 2; //change to actual param count Object[] params = new Object[paramCount]; // Begin customer-written code to populate params array params[0] = bean.getId(); params[1] = new Float(bean.getBalance()); // End customer-written code to populate params array Object result = helper.invokeJAXRPCCall( service, port, operation, returnType, endpointAddress, params); boolean success = ((Boolean) result).booleanValue(); if (!success) { noSuchEntity = new javax.ejb.NoSuchEntityException(bean.getId().toString()); } } catch (ResourceException re) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbStore(AccountBean, AccessIntent, IndexedRecord, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbStore(AccountBean, AccessIntent, IndexedRecord, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (noSuchEntity != null) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbStore(AccountBean, AccessIntent, IndexedRecord, Object)", noSuchEntity); throw noSuchEntity; } log.exiting("AccountBeanUserDefinedPushDownMethodsImpl", "ejbStore(AccountBean, AccessIntent, IndexedRecord, Object)"); }
/** * User-defined push-down method ejbRemove. * If the bean does not exist in the backend datastore, then you should * throw a javax.ejb.RemoveException. * * @param bean Reference to the bean implementation class * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @exception javax.ejb.RemoveException Thrown if an exception occurs deleting bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public void ejbRemove( AccountBean bean, AccessIntent accessIntent, Object connection) throws javax.ejb.RemoveException, ResourceException { log.entering("AccountBeanUserDefinedPushDownMethodsImpl", "ejbRemove(AccountBean, AccessIntent, Object)", new Object[] {bean, accessIntent, connection}); //The following code uses the JAX-RPC Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) JAX-RPC //stubs (produced by a tool such as wscompile or WSDL2Java) if desired. if (service == null) init(); javax.ejb.RemoveException removeEx = null; try { javax.xml.namespace.QName operation = new javax.xml.namespace.QName("deleteAccount"); // Change line below if operation returns a response (that is, if it is non-void) // For example, if it returns a float, then set returnType as follows: // returnType = new QName("http://www.w3.org/2001/XMLSchema", "float"); javax.xml.namespace.QName returnType = new javax.xml.namespace.QName( "http://www.w3.org/2001/XMLSchema", "boolean"); int paramCount = 1; //change to actual param count Object[] params = new Object[paramCount]; // Begin customer-written code to populate params array params[0] = bean.getId(); // End customer-written code to populate params array Object result = helper.invokeJAXRPCCall( service, port, operation, returnType, endpointAddress, params); boolean success = ((Boolean) result).booleanValue(); if (!success) removeEx = new javax.ejb.RemoveException(bean.getId().toString()); } catch (ResourceException re) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbRemove(AccountBean, AccessIntent, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbRemove(AccountBean, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (removeEx != null) { log.throwing("AccountBeanUserDefinedPushDownMethodsImpl", "ejbRemove(AccountBean, AccessIntent, Object)", removeEx); throw removeEx; } log.exiting("AccountBeanUserDefinedPushDownMethodsImpl", "ejbRemove(AccountBean, AccessIntent, Object)"); }
/** * User-defined push-down method ejbFindEmployees&ByDepartmentKey. * For single object finders, if the bean does not exist in the backend * datastore, then you should throw a javax.ejb.ObjectNotFoundException. * For multi-object finders, if no results are found in the backend * datastore, then you should return an empty Record. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @return The return type of this finder method is a Record of Records, * each inner record of which contains the values of the bean's CMP fields, * with primitives wrapped (such as a java.lang.Integer for an int). * Note that with single-bean finders, like ejbFindByPrimaryKey, the outer * record will contain exactly one inner record, whereas with multi-bean * finders the outer record will contain zero or more inner records. The * order of the fields of the inner record must be as follows: * Position #0: id * Position #1: name * Position #2: salary * Position #3: department_id * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindEmployeesByDepartmentKey( java.lang.Integer arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { log.entering("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbFindEmployeesByDepartmentKey(java.lang.Integer, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); //The following code uses the SCA Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) SCA //stubs (similar to an RMI client) if desired. IndexedRecord returnValue = helper.createCCIIndexedRecord(); try { commonj.sdo.DataObject sdo = helper.createSDO( "Example2Backend", "cmrFinder"); // Begin customer-written code to populate SDO sdo.set(0, arg0); // End customer-written code to populate SDO Object result = helper.invokeSCAService( "Example2Backend", "cmrFinder", sdo); // Add records to returnValue record as described in this method's JavaDoc java.util.Vector employees = (java.util.Vector) result; for (int index = 0; index < employees.size(); index++) { com.ibm.cmpa.example2.EmployeeData empData = (com.ibm.cmpa.example2.EmployeeData) employees.get(index); IndexedRecord employee = helper.createCCIIndexedRecord(); employee.set(0, empData.getId()); employee.set(1, empData.getName()); employee.set(2, empData.getSalary()); employee.set(3, empData.getDeptId()); returnValue.add(employee); } } catch (ResourceException re) { log.throwing("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbFindEmployeesByDepartmentKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbFindEmployeesByDepartmentKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. log.exiting("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbFindEmployeesByDepartmentKey(java.lang.Integer, AccessIntent, Object)", returnValue); return returnValue; }
请注意,read-ahead 可以跨多个 CMR。例如,Corporation 可能具有多个 Division,而每个 Division
有多个 Department,每个 Department 有多名 Employee,以 Division
上的查找程序为例,该查找程序对后端数据存储的一次访问可以返回该 Division 上的数据,也可以返回其所有的 Department
上的数据及这些 Department 中的每个 Employee 上的数据。为查找程序生成的 JavaDoc
注释将说明,根据部署描述符中指定的 read-ahead 设置,哪个 Bean 字段映射到 IndexedRecord
中的哪个位置,如下面的示例所示。
/** * User-defined push-down method ejbFindByPrimaryKey. * For single object finders, if the bean does not exist in the backend * datastore, then you should throw a javax.ejb.ObjectNotFoundException. * For multi-object finders, if no results are found in the backend * datastore, then you should return an empty Record. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @return The return type of this finder method is a Record of Records, * each inner record of which contains the values of the bean's CMP fields, * with primitives wrapped (such as a java.lang.Integer for an int). * Note that with single-bean finders, like ejbFindByPrimaryKey, the outer * record will contain exactly one inner record (unless this bean has a * 1-to-many CMR and read-ahead has been enabled), whereas with multi-bean * finders the outer record will contain zero or more inner records. The * order of the fields of the inner record must be as follows: * Position #0: id * Position #1: description * Position #2: EmployeeBean.id * Position #3: EmployeeBean.name * Position #4: EmployeeBean.salary * Position #5: EmployeeBean.department_id * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbFindByPrimaryKey( java.lang.Integer arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { log.entering("DepartmentBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); //The following code uses the SCA Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) SCA //stubs (similar to an RMI client) if desired. javax.ejb.ObjectNotFoundException notFound = null; IndexedRecord returnValue = helper.createCCIIndexedRecord(); try { commonj.sdo.DataObject sdo = helper.createSDO( "Example2Backend", "retrieveDepartment"); // Begin customer-written code to populate SDO sdo.set(0, arg0); // End customer-written code to populate SDO Object result = helper.invokeSCAService( "Example2Backend", "retrieveDepartment", sdo); // Add records to returnValue record as described in this method's JavaDoc java.util.Vector employees = (java.util.Vector) result; String description = (String) employees.get(0); //first slot is for Department for (int index = 1; index < employees.size(); index++) { com.ibm.cmpa.example2.EmployeeData empData = (com.ibm.cmpa.example2.EmployeeData) employees.get(index); IndexedRecord employee = helper.createCCIIndexedRecord(); employee.set(0, arg0); employee.set(1, description); employee.set(2, empData.getId()); employee.set(3, empData.getName()); employee.set(4, empData.getSalary()); employee.set(5, empData.getDeptId()); returnValue.add(employee); } } catch (ResourceException re) { Throwable cause = re.getCause(); if (cause instanceof javax.ejb.ObjectNotFoundException) { notFound = (javax.ejb.ObjectNotFoundException) cause; } else { log.throwing("DepartmentBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("DepartmentBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. if (notFound != null) { log.throwing("DepartmentBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", notFound); throw notFound; } log.exiting("DepartmentBeanUserDefinedPushDownMethodsImpl", "ejbFindByPrimaryKey(java.lang.Integer, AccessIntent, Object)", returnValue); return returnValue; }
/** * User-defined push-down method ejbSelectSalaries. * For single object finders, if the bean does not exist in the backend * datastore, then you should throw a javax.ejb.ObjectNotFoundException. * For multi-object finders, if no results are found in the backend * datastore, then you should return an empty Record. * * @param arg0 Push-down method Parameter #0 * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @return The return type of this finder method is a Record of Records, * each inner record of which contains the values of the bean's CMP fields, * with primitives wrapped (such as a java.lang.Integer for an int). * Note that ejbSelect methods can be defined to return either individual * CMP fields or entire beans. For the former type, the inner record * should only contain the single CMP field. For the latter type, the * order of the fields of the inner record must be as follows: * Position #0: id * Position #1: name * Position #2: salary * Position #3: department_id * * @exception javax.ejb.FinderException Thrown if an exception occurs retrieving bean data * @exception ResourceException Any other exceptions are wrapped in a * ResourceException. */ public Record ejbSelectSalaries( java.lang.Integer arg0, AccessIntent accessIntent, Object connection) throws javax.ejb.FinderException, ResourceException { log.entering("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbSelectSalaries(java.lang.Integer, AccessIntent, Object)", new Object[] {arg0, accessIntent, connection}); //The following code uses the SCA Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) SCA //stubs (similar to an RMI client) if desired. //EJB-QL: select e.salary from Employee e where e.department.id = ?1 IndexedRecord returnValue = helper.createCCIIndexedRecord(); try { commonj.sdo.DataObject sdo = helper.createSDO( "Example2Backend", "selectEmployeeSalaries"); // Begin customer-written code to populate SDO sdo.set(0, arg0); // End customer-written code to populate SDO Object result = helper.invokeSCAService( "Example2Backend", "selectEmployeeSalaries", sdo); // Add records to returnValue record as described in this method's JavaDoc java.util.Vector salaries = (java.util.Vector) result; for (int index = 0; index < salaries.size(); index++) { Float salary = (Float) salaries.get(index); Record record = helper.createCCIRecord(salary); returnValue.add(record); } } catch (ResourceException re) { log.throwing("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbSelectSalaries(java.lang.Integer, AccessIntent, Object)", re); throw re; } catch (Exception e) { ResourceException re = helper.createResourceException(e, this.getClass()); log.throwing("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbSelectSalaries(java.lang.Integer, AccessIntent, Object)", re); throw re; } //Note that if the return code from the back-end datastore interaction //indicated that a user-defined exception (declared in the push-down //method's signature) should be thrown, then throw it here. log.exiting("EmployeeBeanUserDefinedPushDownMethodsImpl", "ejbSelectSalaries(java.lang.Integer, AccessIntent, Object)", returnValue); return returnValue; }
/** * User-defined push-down method awardRaises. * If the bean no longer exists in the backend datastore, then you should * throw a javax.ejb.NoSuchEntityException. * * @param arg0 Push-down method Parameter #0 * @param bean Reference to the bean implementation class * @param accessIntent Reference to the access intent settings to be used for this method * @param connection The CCI connection to the back-end system. This * connection was previously obtained (by the EJBToRAAdapter implementation) * via connectionFactory.getConnection(connectionSpec). For non-relational, * non-CCI based beans, this will be null and the user will have to manually * connect to the back-end system and close the connection before returning. * * @exception ResourceException Any exceptions are wrapped in a * ResourceException. */ public void awardRaises( float arg0, DepartmentBean bean, AccessIntent accessIntent, Object connection) throws ResourceException { log.entering("DepartmentBeanUserDefinedPushDownMethodsImpl", "awardRaises(float, DepartmentBean, AccessIntent, Object)", new Object[] {new Float(arg0), bean, accessIntent, connection}); //The following code uses the SCA Dynamic Invocation Interface (DII). //You can replace it with code that uses static (strongly-typed) SCA //stubs (similar to an RMI client) if desired. javax.ejb.NoSuchEntityException noSuchEntity = null; try { commonj.sdo.DataObject sdo = helper.createSDO( "Example2Backend", "awardRaises"); // Begin customer-written code to populate SDO sdo.set(0, bean.getId()); sdo.set(1, new Float(arg0)); // End customer-written code to populate SDO Object result = helper.invokeSCAService( "Example2Backend", "awardRaises", sdo); } catch (ResourceException re) { Throwable cause = re.getCause(); if (cause instanceof javax.ejb.NoSu