001/*
002 * Copyright 2002-2017 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.support;
018
019import javax.resource.ResourceException;
020import javax.resource.spi.BootstrapContext;
021import javax.resource.spi.ResourceAdapter;
022import javax.resource.spi.XATerminator;
023import javax.resource.spi.work.WorkManager;
024
025import org.springframework.beans.BeanUtils;
026import org.springframework.beans.factory.DisposableBean;
027import org.springframework.beans.factory.FactoryBean;
028import org.springframework.beans.factory.InitializingBean;
029import org.springframework.lang.Nullable;
030
031/**
032 * {@link org.springframework.beans.factory.FactoryBean} that bootstraps
033 * the specified JCA 1.7 {@link javax.resource.spi.ResourceAdapter},
034 * starting it with a local {@link javax.resource.spi.BootstrapContext}
035 * and exposing it for bean references. It will also stop the ResourceAdapter
036 * on context shutdown. This corresponds to 'non-managed' bootstrap in a
037 * local environment, according to the JCA 1.7 specification.
038 *
039 * <p>This is essentially an adapter for bean-style bootstrapping of a
040 * JCA ResourceAdapter, allowing the BootstrapContext or its elements
041 * (such as the JCA WorkManager) to be specified through bean properties.
042 *
043 * @author Juergen Hoeller
044 * @since 2.0.3
045 * @see #setResourceAdapter
046 * @see #setBootstrapContext
047 * @see #setWorkManager
048 * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
049 * @see javax.resource.spi.ResourceAdapter#stop()
050 */
051public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>, InitializingBean, DisposableBean {
052
053        @Nullable
054        private ResourceAdapter resourceAdapter;
055
056        @Nullable
057        private BootstrapContext bootstrapContext;
058
059        @Nullable
060        private WorkManager workManager;
061
062        @Nullable
063        private XATerminator xaTerminator;
064
065
066        /**
067         * Specify the target JCA ResourceAdapter as class, to be instantiated
068         * with its default configuration.
069         * <p>Alternatively, specify a pre-configured ResourceAdapter instance
070         * through the "resourceAdapter" property.
071         * @see #setResourceAdapter
072         */
073        public void setResourceAdapterClass(Class<? extends ResourceAdapter> resourceAdapterClass) {
074                this.resourceAdapter = BeanUtils.instantiateClass(resourceAdapterClass);
075        }
076
077        /**
078         * Specify the target JCA ResourceAdapter, passed in as configured instance
079         * which hasn't been started yet. This will typically happen as an
080         * inner bean definition, configuring the ResourceAdapter instance
081         * through its vendor-specific bean properties.
082         */
083        public void setResourceAdapter(ResourceAdapter resourceAdapter) {
084                this.resourceAdapter = resourceAdapter;
085        }
086
087        /**
088         * Specify the JCA BootstrapContext to use for starting the ResourceAdapter.
089         * <p>Alternatively, you can specify the individual parts (such as the
090         * JCA WorkManager) as individual references.
091         * @see #setWorkManager
092         * @see #setXaTerminator
093         */
094        public void setBootstrapContext(BootstrapContext bootstrapContext) {
095                this.bootstrapContext = bootstrapContext;
096        }
097
098        /**
099         * Specify the JCA WorkManager to use for bootstrapping the ResourceAdapter.
100         * @see #setBootstrapContext
101         */
102        public void setWorkManager(WorkManager workManager) {
103                this.workManager = workManager;
104        }
105
106        /**
107         * Specify the JCA XATerminator to use for bootstrapping the ResourceAdapter.
108         * @see #setBootstrapContext
109         */
110        public void setXaTerminator(XATerminator xaTerminator) {
111                this.xaTerminator = xaTerminator;
112        }
113
114
115        /**
116         * Builds the BootstrapContext and starts the ResourceAdapter with it.
117         * @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext)
118         */
119        @Override
120        public void afterPropertiesSet() throws ResourceException {
121                if (this.resourceAdapter == null) {
122                        throw new IllegalArgumentException("'resourceAdapter' or 'resourceAdapterClass' is required");
123                }
124                if (this.bootstrapContext == null) {
125                        this.bootstrapContext = new SimpleBootstrapContext(this.workManager, this.xaTerminator);
126                }
127                this.resourceAdapter.start(this.bootstrapContext);
128        }
129
130
131        @Override
132        @Nullable
133        public ResourceAdapter getObject() {
134                return this.resourceAdapter;
135        }
136
137        @Override
138        public Class<? extends ResourceAdapter> getObjectType() {
139                return (this.resourceAdapter != null ? this.resourceAdapter.getClass() : ResourceAdapter.class);
140        }
141
142        @Override
143        public boolean isSingleton() {
144                return true;
145        }
146
147
148        /**
149         * Stops the ResourceAdapter.
150         * @see javax.resource.spi.ResourceAdapter#stop()
151         */
152        @Override
153        public void destroy() {
154                if (this.resourceAdapter != null) {
155                        this.resourceAdapter.stop();
156                }
157        }
158
159}