Skip to content

Commit 3fe724b

Browse files
db: Prevent NullPointerException on GenericDaoBase (#4268)
* Prevent NullPointerException on GenericDaoBase * Fix checkstyle: remove unused import
1 parent c383269 commit 3fe724b

2 files changed

Lines changed: 79 additions & 35 deletions

File tree

framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ public abstract class GenericDaoBase<T, ID extends Serializable> extends Compone
162162
protected static final String SELECT_LAST_INSERT_ID_SQL = "SELECT LAST_INSERT_ID()";
163163
public static final Date DATE_TO_NULL = new Date(Long.MIN_VALUE);
164164

165+
private static final String INTEGRITY_CONSTRAINT_VIOLATION = "23000";
166+
private static final int DUPLICATE_ENTRY_ERRO_CODE = 1062;
167+
165168
protected static final SequenceFetcher s_seqFetcher = SequenceFetcher.getInstance();
166169

167170
public static <J> GenericDao<? extends J, ? extends Serializable> getDao(Class<J> entityType) {
@@ -850,13 +853,23 @@ public int update(UpdateBuilder ub, final SearchCriteria<?> sc, Integer rows) {
850853
ub.clear();
851854
return result;
852855
} catch (final SQLException e) {
853-
if (e.getSQLState().equals("23000") && e.getErrorCode() == 1062) {
854-
throw new EntityExistsException("Entity already exists ", e);
855-
}
856+
handleEntityExistsException(e);
856857
throw new CloudRuntimeException("DB Exception on: " + pstmt, e);
857858
}
858859
}
859860

861+
/**
862+
* If the SQLException.getSQLState is of 23000 (Integrity Constraint Violation), and the Error Code is 1062 (Duplicate Entry), throws EntityExistsException.
863+
* @throws EntityExistsException
864+
*/
865+
protected static void handleEntityExistsException(SQLException e) throws EntityExistsException {
866+
boolean isIntegrityConstantViolation = INTEGRITY_CONSTRAINT_VIOLATION.equals(e.getSQLState());
867+
boolean isErrorCodeOfDuplicateEntry = e.getErrorCode() == DUPLICATE_ENTRY_ERRO_CODE;
868+
if (isIntegrityConstantViolation && isErrorCodeOfDuplicateEntry) {
869+
throw new EntityExistsException("Entity already exists ", e);
870+
}
871+
}
872+
860873
@DB()
861874
protected Attribute findAttributeByFieldName(String name) {
862875
return _allAttributes.get(name);
@@ -1450,11 +1463,8 @@ public T persist(final T entity) {
14501463
}
14511464
txn.commit();
14521465
} catch (final SQLException e) {
1453-
if (e.getSQLState().equals("23000") && e.getErrorCode() == 1062) {
1454-
throw new EntityExistsException("Entity already exists: ", e);
1455-
} else {
1456-
throw new CloudRuntimeException("DB Exception on: " + pstmt, e);
1457-
}
1466+
handleEntityExistsException(e);
1467+
throw new CloudRuntimeException("DB Exception on: " + pstmt, e);
14581468
} catch (IllegalArgumentException e) {
14591469
throw new CloudRuntimeException("Problem with getting the ec attribute ", e);
14601470
} catch (IllegalAccessException e) {

framework/db/src/test/java/com/cloud/utils/db/GenericDaoBaseTest.java

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,132 +20,166 @@
2020
import java.sql.SQLException;
2121

2222
import org.junit.Assert;
23+
import org.junit.Before;
2324
import org.junit.Test;
2425
import org.junit.runner.RunWith;
2526
import org.mockito.Mock;
2627
import org.mockito.Mockito;
27-
import org.mockito.runners.MockitoJUnitRunner;
28+
import org.mockito.junit.MockitoJUnitRunner;
29+
30+
import javax.persistence.EntityExistsException;
2831

2932
@RunWith(MockitoJUnitRunner.class)
3033
public class GenericDaoBaseTest {
3134
@Mock
3235
ResultSet resultSet;
36+
@Mock
37+
SQLException mockedSQLException;
3338

34-
@Test
35-
public void getObjectBoolean() throws SQLException {
39+
private static final String INTEGRITY_CONSTRAINT_VIOLATION = "23000";
40+
private static final int DUPLICATE_ENTRY_ERRO_CODE = 1062;
41+
42+
@Before
43+
public void prepareTests() throws SQLException {
3644
Mockito.when(resultSet.getObject(1)).thenReturn(false);
3745
Mockito.when(resultSet.getBoolean(1)).thenReturn(false);
46+
Mockito.when(resultSet.getObject(1)).thenReturn((short) 1);
47+
Mockito.when(resultSet.getShort(1)).thenReturn((short) 1);
48+
Mockito.when(resultSet.getObject(1)).thenReturn(0.1f);
49+
Mockito.when(resultSet.getFloat(1)).thenReturn(0.1f);
50+
Mockito.when(resultSet.getObject(1)).thenReturn(0.1d);
51+
Mockito.when(resultSet.getDouble(1)).thenReturn(0.1d);
52+
Mockito.when(resultSet.getObject(1)).thenReturn(1l);
53+
Mockito.when(resultSet.getLong(1)).thenReturn(1l);
54+
Mockito.when(resultSet.getInt(1)).thenReturn(1);
55+
Mockito.when(resultSet.getObject(1)).thenReturn((byte) 1);
56+
Mockito.when(resultSet.getByte(1)).thenReturn((byte) 1);
57+
}
58+
59+
@Test
60+
public void getObjectBoolean() throws SQLException {
3861
Assert.assertFalse(GenericDaoBase
3962
.getObject(Boolean.class, resultSet, 1));
4063
Mockito.verify(resultSet).getBoolean(1);
4164
}
4265

4366
@Test
4467
public void getObjectPrimitiveBoolean() throws SQLException {
45-
Mockito.when(resultSet.getObject(1)).thenReturn(false);
46-
Mockito.when(resultSet.getBoolean(1)).thenReturn(false);
4768
Assert.assertFalse(GenericDaoBase
4869
.getObject(boolean.class, resultSet, 1));
4970
Mockito.verify(resultSet).getBoolean(1);
5071
}
5172

5273
@Test
5374
public void getObjectPrimitiveShort() throws SQLException {
54-
Mockito.when(resultSet.getObject(1)).thenReturn((short) 1);
55-
Mockito.when(resultSet.getShort(1)).thenReturn((short) 1);
5675
Assert.assertEquals(Short.valueOf((short) 1),
5776
GenericDaoBase.getObject(short.class, resultSet, 1));
5877
Mockito.verify(resultSet).getShort(1);
5978
}
6079

6180
@Test
6281
public void getObjectShort() throws SQLException {
63-
Mockito.when(resultSet.getObject(1)).thenReturn((short) 1);
64-
Mockito.when(resultSet.getShort(1)).thenReturn((short) 1);
6582
Assert.assertEquals(Short.valueOf((short) 1),
6683
GenericDaoBase.getObject(Short.class, resultSet, 1));
6784
Mockito.verify(resultSet).getShort(1);
6885
}
6986

7087
@Test
7188
public void getObjectFloat() throws SQLException {
72-
Mockito.when(resultSet.getObject(1)).thenReturn(0.1f);
73-
Mockito.when(resultSet.getFloat(1)).thenReturn(0.1f);
7489
Assert.assertEquals(0.1f,
7590
GenericDaoBase.getObject(Float.class, resultSet, 1), 0.1);
7691
Mockito.verify(resultSet).getFloat(1);
7792
}
7893

7994
@Test
8095
public void getObjectPrimitiveFloat() throws SQLException {
81-
Mockito.when(resultSet.getObject(1)).thenReturn(0.1f);
82-
Mockito.when(resultSet.getFloat(1)).thenReturn(0.1f);
8396
Assert.assertEquals(0.1f,
8497
GenericDaoBase.getObject(float.class, resultSet, 1), 0.1);
8598
Mockito.verify(resultSet).getFloat(1);
8699
}
87100

88101
@Test
89102
public void getObjectPrimitiveDouble() throws SQLException {
90-
Mockito.when(resultSet.getObject(1)).thenReturn(0.1d);
91-
Mockito.when(resultSet.getDouble(1)).thenReturn(0.1d);
92103
Assert.assertEquals(0.1d,
93104
GenericDaoBase.getObject(double.class, resultSet, 1), 0.1);
94105
Mockito.verify(resultSet).getDouble(1);
95106
}
96107

97108
@Test
98109
public void getObjectDouble() throws SQLException {
99-
Mockito.when(resultSet.getObject(1)).thenReturn(0.1d);
100-
Mockito.when(resultSet.getDouble(1)).thenReturn(0.1d);
101110
Assert.assertEquals(0.1d,
102111
GenericDaoBase.getObject(Double.class, resultSet, 1), 0.1);
103112
Mockito.verify(resultSet).getDouble(1);
104113
}
105114

106115
@Test
107116
public void getObjectLong() throws SQLException {
108-
Mockito.when(resultSet.getObject(1)).thenReturn(1l);
109-
Mockito.when(resultSet.getLong(1)).thenReturn(1l);
110117
Assert.assertEquals((Long) 1l,
111118
GenericDaoBase.getObject(Long.class, resultSet, 1));
112119
Mockito.verify(resultSet).getLong(1);
113120
}
114121

115122
@Test
116123
public void getObjectPrimitiveLong() throws SQLException {
117-
Mockito.when(resultSet.getObject(1)).thenReturn(1l);
118-
Mockito.when(resultSet.getLong(1)).thenReturn(1l);
119124
Assert.assertEquals((Long) 1l,
120125
GenericDaoBase.getObject(long.class, resultSet, 1));
121126
Mockito.verify(resultSet).getLong(1);
122127
}
123128

124129
@Test
125130
public void getObjectPrimitiveInt() throws SQLException {
126-
Mockito.when(resultSet.getObject(1)).thenReturn(1l);
127-
Mockito.when(resultSet.getInt(1)).thenReturn(1);
128131
Assert.assertEquals((Integer) 1,
129132
GenericDaoBase.getObject(int.class, resultSet, 1));
130133
Mockito.verify(resultSet).getInt(1);
131134
}
132135

133136
@Test
134137
public void getObjectInteger() throws SQLException {
135-
Mockito.when(resultSet.getObject(1)).thenReturn(1l);
136-
Mockito.when(resultSet.getInt(1)).thenReturn(1);
137138
Assert.assertEquals((Integer) 1,
138139
GenericDaoBase.getObject(Integer.class, resultSet, 1));
139140
Mockito.verify(resultSet).getInt(1);
140141
}
141142

142143
@Test
143144
public void getObjectPrimitiveByte() throws SQLException {
144-
Mockito.when(resultSet.getObject(1)).thenReturn((byte) 1);
145-
Mockito.when(resultSet.getByte(1)).thenReturn((byte) 1);
146145
Assert.assertTrue((byte) 1 == GenericDaoBase.getObject(byte.class,
147146
resultSet, 1));
148147
Mockito.verify(resultSet).getByte(1);
149148
}
150149

150+
@Test
151+
public void handleEntityExistsExceptionTestNoMatchForEntityExists() {
152+
Mockito.when(mockedSQLException.getErrorCode()).thenReturn(123);
153+
Mockito.when(mockedSQLException.getSQLState()).thenReturn("123");
154+
GenericDaoBase.handleEntityExistsException(mockedSQLException);
155+
}
156+
157+
@Test
158+
public void handleEntityExistsExceptionTestIntegrityConstraint() {
159+
Mockito.when(mockedSQLException.getErrorCode()).thenReturn(123);
160+
Mockito.when(mockedSQLException.getSQLState()).thenReturn(INTEGRITY_CONSTRAINT_VIOLATION);
161+
GenericDaoBase.handleEntityExistsException(mockedSQLException);
162+
}
163+
164+
@Test
165+
public void handleEntityExistsExceptionTestIntegrityConstraintNull() {
166+
Mockito.when(mockedSQLException.getErrorCode()).thenReturn(123);
167+
Mockito.when(mockedSQLException.getSQLState()).thenReturn(null);
168+
GenericDaoBase.handleEntityExistsException(mockedSQLException);
169+
}
170+
171+
@Test
172+
public void handleEntityExistsExceptionTestDuplicateEntryErrorCode() {
173+
Mockito.when(mockedSQLException.getErrorCode()).thenReturn(DUPLICATE_ENTRY_ERRO_CODE);
174+
Mockito.when(mockedSQLException.getSQLState()).thenReturn("123");
175+
GenericDaoBase.handleEntityExistsException(mockedSQLException);
176+
}
177+
178+
@Test(expected = EntityExistsException.class)
179+
public void handleEntityExistsExceptionTestExpectEntityExistsException() {
180+
Mockito.when(mockedSQLException.getErrorCode()).thenReturn(DUPLICATE_ENTRY_ERRO_CODE);
181+
Mockito.when(mockedSQLException.getSQLState()).thenReturn(INTEGRITY_CONSTRAINT_VIOLATION);
182+
GenericDaoBase.handleEntityExistsException(mockedSQLException);
183+
}
184+
151185
}

0 commit comments

Comments
 (0)