/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.ignite.internal.processors.resource;
import java.util.concurrent.Callable;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteSpring;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.util.typedef.G;
import org.apache.ignite.lang.IgniteCallable;
import org.apache.ignite.resources.SpringResource;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Tests for injected resource.
*/
@SuppressWarnings("unused")
public class GridSpringResourceInjectionSelfTest extends GridCommonAbstractTest {
/** Bean name. */
private static final String DUMMY_BEAN = "dummyResourceBean";
/** Test grid with Spring context. */
private static Ignite grid;
/** {@inheritDoc} */
@Override public void beforeTestsStarted() throws Exception {
grid = IgniteSpring.start(new ClassPathXmlApplicationContext(
"/org/apache/ignite/internal/processors/resource/spring-resource.xml"));
}
/** {@inheritDoc} */
@Override public void afterTestsStopped() throws Exception {
stopAllGrids();
}
/**
* @throws Exception If failed.
*/
public void testClosureFieldByResourceName() throws Exception {
grid.compute().call(new IgniteCallable<Object>() {
@SpringResource(resourceName = DUMMY_BEAN)
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
});
}
/**
* @throws Exception If failed.
*/
public void testClosureFieldByResourceClass() throws Exception {
grid.compute().call(new IgniteCallable<Object>() {
@SpringResource(resourceClass = DummyResourceBean.class)
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
});
}
/**
* @throws Exception If failed.
*/
public void testClosureFieldByResourceClassWithMultipleBeans() throws Exception {
IgniteConfiguration anotherCfg = new IgniteConfiguration();
anotherCfg.setIgniteInstanceName("anotherGrid");
Ignite anotherGrid = IgniteSpring.start(anotherCfg, new ClassPathXmlApplicationContext(
"/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml"));
Throwable err = assertError(new IgniteCallable<Object>() {
@SpringResource(resourceClass = DummyResourceBean.class)
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
}, anotherGrid, null);
assertTrue("Unexpected message: " + err.getMessage(), err.getMessage().startsWith("No qualifying bean of type " +
"'org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean'" +
" available: expected single matching bean but found 2:"));
G.stop("anotherGrid", false);
}
/**
* Resource injection with non-existing resource name.
*/
public void testClosureFieldWithWrongResourceName() {
assertError(new IgniteCallable<Object>() {
@SpringResource(resourceName = "nonExistentResource")
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "No bean named 'nonExistentResource' available");
}
/**
* Resource injection with non-existing resource class.
*/
public void testClosureFieldWithWrongResourceClass() {
assertError(new IgniteCallable<Object>() {
@SpringResource(resourceClass = AnotherDummyResourceBean.class)
private transient AnotherDummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "No qualifying bean of type 'org.apache.ignite.internal.processors.resource." +
"GridSpringResourceInjectionSelfTest$AnotherDummyResourceBean' available");
}
/**
* Resource injection with both resource and class set (ambiguity).
*/
public void testClosureFieldByResourceClassAndName() {
assertError(new IgniteCallable<Object>() {
@SpringResource(resourceClass = DummyResourceBean.class, resourceName = DUMMY_BEAN)
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "Either bean name or its class must be specified in @SpringResource, but not both");
}
/**
* Resource injection with no name and class set.
*/
public void testClosureFieldWithNoParams() {
assertError(new IgniteCallable<Object>() {
@SpringResource
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "Either bean name or its class must be specified in @SpringResource, but not both");
}
/**
* @throws Exception If failed.
*/
public void testClosureMethodWithResourceName() throws Exception {
grid.compute().call(new IgniteCallable<Object>() {
private DummyResourceBean dummyRsrcBean;
@SpringResource(resourceName = DUMMY_BEAN)
private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
assertNotNull(dummyRsrcBean);
this.dummyRsrcBean = dummyRsrcBean;
}
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
});
}
/**
* @throws Exception If failed.
*/
public void testClosureMethodWithResourceClass() throws Exception {
grid.compute().call(new IgniteCallable<Object>() {
private DummyResourceBean dummyRsrcBean;
@SpringResource(resourceClass = DummyResourceBean.class)
private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
assertNotNull(dummyRsrcBean);
this.dummyRsrcBean = dummyRsrcBean;
}
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
});
}
/**
* @throws Exception If failed.
*/
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public void testClosureMethodWithResourceClassWithMultipleBeans() throws Exception {
IgniteConfiguration anotherCfg = new IgniteConfiguration();
anotherCfg.setIgniteInstanceName("anotherGrid");
Ignite anotherGrid = IgniteSpring.start(anotherCfg, new ClassPathXmlApplicationContext(
"/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml"));
try {
Throwable err = assertError(new IgniteCallable<Object>() {
private DummyResourceBean dummyRsrcBean;
@SpringResource(resourceClass = DummyResourceBean.class)
private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
assertNotNull(dummyRsrcBean);
this.dummyRsrcBean = dummyRsrcBean;
}
@Override public Object call() throws Exception {
assertNotNull(dummyRsrcBean);
return null;
}
}, anotherGrid, null);
assertTrue("Unexpected message: " + err.getMessage(), err.getMessage().startsWith("No qualifying bean of type " +
"'org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean'" +
" available: expected single matching bean but found 2:"));
}
finally {
G.stop("anotherGrid", false);
}
}
/**
* Resource injection with non-existing resource name.
*/
public void testClosureMethodWithWrongResourceName() {
assertError(new IgniteCallable<Object>() {
private DummyResourceBean dummyRsrcBean;
@SpringResource(resourceName = "nonExistentResource")
private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
// No-op.
}
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "No bean named 'nonExistentResource' available");
}
/**
* Resource injection with non-existing resource class.
*/
public void testClosureMethodWithWrongResourceClass() {
assertError(new IgniteCallable<Object>() {
private AnotherDummyResourceBean dummyRsrcBean;
@SpringResource(resourceClass = AnotherDummyResourceBean.class)
private void setDummyResourceBean(AnotherDummyResourceBean dummyRsrcBean) {
// No-op.
}
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "No qualifying bean of type 'org.apache.ignite.internal.processors.resource" +
".GridSpringResourceInjectionSelfTest$AnotherDummyResourceBean' available");
}
/**
* Resource injection with both resource and class set (ambiguity).
*/
public void testClosureMethodByResourceClassAndName() {
assertError(new IgniteCallable<Object>() {
@SpringResource(resourceClass = DummyResourceBean.class, resourceName = DUMMY_BEAN)
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "Either bean name or its class must be specified in @SpringResource, but not both");
}
/**
* Resource injection with no params.
*/
public void testClosureMethodWithNoParams() {
assertError(new IgniteCallable<Object>() {
@SpringResource
private transient DummyResourceBean dummyRsrcBean;
@Override public Object call() throws Exception {
assertNull(dummyRsrcBean);
return null;
}
}, "Either bean name or its class must be specified in @SpringResource, but not both");
}
/**
* @param job {@link IgniteCallable} to be run
* @param grid Node.
* @param expEMsg Message that {@link IgniteException} thrown from <tt>job</tt> should bear
* @return Thrown error.
*/
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
private Throwable assertError(final IgniteCallable<?> job, final Ignite grid, String expEMsg) {
return GridTestUtils.assertThrows(log, new Callable<Object>() {
@Override public Object call() throws Exception {
grid.compute(grid.cluster().forLocal()).call(job);
return null;
}
}, IgniteException.class, expEMsg);
}
/**
* @param job {@link IgniteCallable} to be run
* @param expEMsg Message that {@link IgniteException} thrown from <tt>job</tt> should bear
*/
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
private void assertError(final IgniteCallable<?> job, String expEMsg) {
assertError(job, grid, expEMsg);
}
/**
* Dummy resource bean.
*/
public static class DummyResourceBean {
/**
*
*/
public DummyResourceBean() {
// No-op.
}
}
/**
* Another dummy resource bean.
*/
private static class AnotherDummyResourceBean {
/**
*
*/
public AnotherDummyResourceBean() {
// No-op.
}
}
}