001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jca.cci.object; 018 019import java.sql.SQLException; 020 021import javax.resource.ResourceException; 022import javax.resource.cci.ConnectionFactory; 023import javax.resource.cci.InteractionSpec; 024import javax.resource.cci.Record; 025import javax.resource.cci.RecordFactory; 026 027import org.springframework.dao.DataAccessException; 028import org.springframework.jca.cci.core.RecordCreator; 029import org.springframework.jca.cci.core.RecordExtractor; 030import org.springframework.lang.Nullable; 031import org.springframework.util.Assert; 032 033/** 034 * EIS operation object that expects mapped input and output objects, 035 * converting to and from CCI Records. 036 * 037 * <p>Concrete subclasses must implement the abstract 038 * {@code createInputRecord(RecordFactory, Object)} and 039 * {@code extractOutputData(Record)} methods, to create an input 040 * Record from an object and to convert an output Record into an object, 041 * respectively. 042 * 043 * @author Thierry Templier 044 * @author Juergen Hoeller 045 * @since 1.2 046 * @see #createInputRecord(javax.resource.cci.RecordFactory, Object) 047 * @see #extractOutputData(javax.resource.cci.Record) 048 */ 049public abstract class MappingRecordOperation extends EisOperation { 050 051 /** 052 * Constructor that allows use as a JavaBean. 053 */ 054 public MappingRecordOperation() { 055 } 056 057 /** 058 * Convenient constructor with ConnectionFactory and specifications 059 * (connection and interaction). 060 * @param connectionFactory the ConnectionFactory to use to obtain connections 061 */ 062 public MappingRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) { 063 getCciTemplate().setConnectionFactory(connectionFactory); 064 setInteractionSpec(interactionSpec); 065 } 066 067 /** 068 * Set a RecordCreator that should be used for creating default output Records. 069 * <p>Default is none: CCI's {@code Interaction.execute} variant 070 * that returns an output Record will be called. 071 * <p>Specify a RecordCreator here if you always need to call CCI's 072 * {@code Interaction.execute} variant with a passed-in output Record. 073 * This RecordCreator will then be invoked to create a default output Record instance. 074 * @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record) 075 * @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record) 076 * @see org.springframework.jca.cci.core.CciTemplate#setOutputRecordCreator 077 */ 078 public void setOutputRecordCreator(RecordCreator creator) { 079 getCciTemplate().setOutputRecordCreator(creator); 080 } 081 082 /** 083 * Execute the interaction encapsulated by this operation object. 084 * @param inputObject the input data, to be converted to a Record 085 * by the {@code createInputRecord} method 086 * @return the output data extracted with the {@code extractOutputData} method 087 * @throws DataAccessException if there is any problem 088 * @see #createInputRecord 089 * @see #extractOutputData 090 */ 091 @Nullable 092 public Object execute(Object inputObject) throws DataAccessException { 093 InteractionSpec interactionSpec = getInteractionSpec(); 094 Assert.state(interactionSpec != null, "No InteractionSpec set"); 095 return getCciTemplate().execute( 096 interactionSpec, new RecordCreatorImpl(inputObject), new RecordExtractorImpl()); 097 } 098 099 100 /** 101 * Subclasses must implement this method to generate an input Record 102 * from an input object passed into the {@code execute} method. 103 * @param inputObject the passed-in input object 104 * @return the CCI input Record 105 * @throws ResourceException if thrown by a CCI method, to be auto-converted 106 * to a DataAccessException 107 * @see #execute(Object) 108 */ 109 protected abstract Record createInputRecord(RecordFactory recordFactory, Object inputObject) 110 throws ResourceException, DataAccessException; 111 112 /** 113 * Subclasses must implement this method to convert the Record returned 114 * by CCI execution into a result object for the {@code execute} method. 115 * @param outputRecord the Record returned by CCI execution 116 * @return the result object 117 * @throws ResourceException if thrown by a CCI method, to be auto-converted 118 * to a DataAccessException 119 * @see #execute(Object) 120 */ 121 protected abstract Object extractOutputData(Record outputRecord) 122 throws ResourceException, SQLException, DataAccessException; 123 124 125 /** 126 * Implementation of RecordCreator that calls the enclosing 127 * class's {@code createInputRecord} method. 128 */ 129 protected class RecordCreatorImpl implements RecordCreator { 130 131 private final Object inputObject; 132 133 public RecordCreatorImpl(Object inObject) { 134 this.inputObject = inObject; 135 } 136 137 @Override 138 public Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException { 139 return createInputRecord(recordFactory, this.inputObject); 140 } 141 } 142 143 144 /** 145 * Implementation of RecordExtractor that calls the enclosing 146 * class's {@code extractOutputData} method. 147 */ 148 protected class RecordExtractorImpl implements RecordExtractor<Object> { 149 150 @Override 151 public Object extractData(Record record) throws ResourceException, SQLException, DataAccessException { 152 return extractOutputData(record); 153 } 154 } 155 156}