Skip to content

Commit cac4d58

Browse files
committed
Avoid NPE on MyBatisCursorItemReader
Fixes mybatisgh-237 (cherry picked from commit a4b9394)
1 parent f701571 commit cac4d58

File tree

3 files changed

+104
-2
lines changed

3 files changed

+104
-2
lines changed

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@
257257
<scope>test</scope>
258258
</dependency>
259259

260+
<dependency>
261+
<groupId>org.mockito</groupId>
262+
<artifactId>mockito-core</artifactId>
263+
<version>2.10.0</version>
264+
<scope>test</scope>
265+
</dependency>
266+
260267
</dependencies>
261268

262269
<build>

src/main/java/org/mybatis/spring/batch/MyBatisCursorItemReader.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,12 @@ protected void doOpen() throws Exception {
7171

7272
@Override
7373
protected void doClose() throws Exception {
74-
cursor.close();
75-
sqlSession.close();
74+
if (cursor != null) {
75+
cursor.close();
76+
}
77+
if (sqlSession != null) {
78+
sqlSession.close();
79+
}
7680
cursorIterator = null;
7781
}
7882

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* Copyright 2010-2017 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.mybatis.spring.batch;
17+
18+
import org.apache.ibatis.session.ExecutorType;
19+
import org.apache.ibatis.session.SqlSession;
20+
import org.apache.ibatis.session.SqlSessionFactory;
21+
import org.hamcrest.core.Is;
22+
import org.hamcrest.core.IsInstanceOf;
23+
import org.junit.Assert;
24+
import org.junit.Before;
25+
import org.junit.Test;
26+
import org.mockito.*;
27+
import org.springframework.batch.item.ExecutionContext;
28+
import org.springframework.batch.item.ItemStreamException;
29+
30+
/**
31+
* Tests for {@link MyBatisCursorItemReader}.
32+
*/
33+
public class MyBatisCursorItemReaderTest {
34+
35+
@Mock
36+
private SqlSessionFactory sqlSessionFactory;
37+
38+
@Mock
39+
private SqlSession sqlSession;
40+
41+
@Before
42+
public void setUp() {
43+
MockitoAnnotations.initMocks(this);
44+
}
45+
46+
@Test
47+
public void testCloseOnFailing() throws Exception {
48+
49+
Mockito.when(this.sqlSessionFactory.openSession(ExecutorType.SIMPLE))
50+
.thenReturn(this.sqlSession);
51+
Mockito.when(this.sqlSession.selectCursor(Mockito.eq("selectFoo"), Mockito.anyMap()))
52+
.thenThrow(new RuntimeException("error."));
53+
54+
MyBatisCursorItemReader<Foo> itemReader = new MyBatisCursorItemReader<Foo>();
55+
itemReader.setSqlSessionFactory(this.sqlSessionFactory);
56+
itemReader.setQueryId("selectFoo");
57+
itemReader.afterPropertiesSet();
58+
59+
ExecutionContext executionContext = new ExecutionContext();
60+
try {
61+
itemReader.open(executionContext);
62+
} catch (ItemStreamException e) {
63+
Assert.assertThat(e.getMessage(), Is.is("Failed to initialize the reader"));
64+
Assert.assertThat(e.getCause(), IsInstanceOf.instanceOf(RuntimeException.class));
65+
Assert.assertThat(e.getCause().getMessage(), Is.is("error."));
66+
} finally {
67+
itemReader.close();
68+
Mockito.verify(this.sqlSession).close();
69+
}
70+
71+
}
72+
73+
@Test
74+
public void testCloseBeforeOpen() {
75+
MyBatisCursorItemReader<Foo> itemReader = new MyBatisCursorItemReader<Foo>();
76+
itemReader.close();
77+
}
78+
79+
private static class Foo {
80+
private final String name;
81+
82+
public Foo(String name) {
83+
this.name = name;
84+
}
85+
86+
public String getName() {
87+
return this.name;
88+
}
89+
}
90+
91+
}

0 commit comments

Comments
 (0)