Skip to content

Commit 826595e

Browse files
[b/420369667] fix NPE for Oozie end date (#910)
* fix NPE for Oozie end date * add test for filtering jobs with null end date * fix code style * remove empty line
1 parent fce8a1e commit 826595e

File tree

5 files changed

+83
-4
lines changed

5 files changed

+83
-4
lines changed

dumper/app/src/main/java/com/google/edwmigration/dumper/application/dumper/connector/hadoop/oozie/AbstractOozieJobsTask.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.List;
3535
import javax.annotation.CheckForNull;
3636
import javax.annotation.Nonnull;
37+
import javax.annotation.Nullable;
3738
import org.apache.commons.beanutils.PropertyUtils;
3839
import org.apache.commons.csv.CSVFormat;
3940
import org.apache.commons.csv.CSVPrinter;
@@ -100,7 +101,8 @@ protected Void doRun(TaskRunContext context, @Nonnull ByteSink sink, @Nonnull Ha
100101
for (J job : jobs) {
101102
Date currentJobEndTime = getJobEndTime(job);
102103
boolean inDateRange =
103-
minJobEndTimeTimestamp <= currentJobEndTime.getTime()
104+
currentJobEndTime != null
105+
&& minJobEndTimeTimestamp <= currentJobEndTime.getTime()
104106
&& currentJobEndTime.getTime() < maxJobEndTimeTimestamp;
105107
if (!inDateRange) {
106108
// It's client side filtering. It's inefficient.
@@ -120,10 +122,10 @@ protected Void doRun(TaskRunContext context, @Nonnull ByteSink sink, @Nonnull Ha
120122

121123
J lastJob = jobs.get(jobs.size() - 1);
122124
Date endTime = getJobEndTime(lastJob);
123-
if (endTime == null) {
124-
break;
125+
boolean isLastJobInProgress = endTime == null;
126+
if (!isLastJobInProgress) {
127+
latestFetchedJobEndTimestamp = endTime.getTime();
125128
}
126-
latestFetchedJobEndTimestamp = endTime.getTime();
127129
offset += jobs.size();
128130
}
129131

@@ -147,6 +149,7 @@ CSVFormat createJobSpecificCSVFormat() {
147149
abstract List<J> fetchJobsWithFilter(
148150
XOozieClient oozieClient, String oozieFilter, int start, int len) throws OozieClientException;
149151

152+
@Nullable
150153
abstract Date getJobEndTime(J job);
151154

152155
private static String toISO(ZonedDateTime dateTime) {

dumper/app/src/test/java/com/google/edwmigration/dumper/application/dumper/connector/hadoop/oozie/OozieBundleJobsTaskTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static org.junit.Assert.assertArrayEquals;
2020
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNull;
2122
import static org.mockito.Mockito.mock;
2223
import static org.mockito.Mockito.verify;
2324
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -61,6 +62,13 @@ public void getJobEndTime_success() throws Exception {
6162
verifyNoMoreInteractions(job);
6263
}
6364

65+
@Test
66+
public void getJobEndTime_nullable() {
67+
BundleJob job = mock(BundleJob.class);
68+
69+
assertNull("null is expected value for end time", task.getJobEndTime(job));
70+
}
71+
6472
@Test
6573
public void csvHeadersContainRequiredFields() {
6674
String[] header = task.createJobSpecificCSVFormat().getHeader();

dumper/app/src/test/java/com/google/edwmigration/dumper/application/dumper/connector/hadoop/oozie/OozieCoordinatorJobsTaskTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static org.junit.Assert.assertArrayEquals;
2020
import static org.junit.Assert.assertEquals;
21+
import static org.junit.Assert.assertNull;
2122
import static org.mockito.Mockito.mock;
2223
import static org.mockito.Mockito.verify;
2324
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -61,6 +62,13 @@ public void getJobEndTime_success() throws Exception {
6162
verifyNoMoreInteractions(job);
6263
}
6364

65+
@Test
66+
public void getJobEndTime_nullable() {
67+
CoordinatorJob job = mock(CoordinatorJob.class);
68+
69+
assertNull("null is expected value for end time", task.getJobEndTime(job));
70+
}
71+
6472
@Test
6573
public void csvHeadersContainRequiredFields() {
6674
String[] header = task.createJobSpecificCSVFormat().getHeader();

dumper/app/src/test/java/com/google/edwmigration/dumper/application/dumper/connector/hadoop/oozie/OozieWorkflowJobsTaskTest.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
2525
import static org.junit.Assert.assertArrayEquals;
2626
import static org.junit.Assert.assertEquals;
27+
import static org.junit.Assert.assertNull;
2728
import static org.junit.Assert.assertThrows;
2829
import static org.mockito.Mockito.mock;
2930
import static org.mockito.Mockito.verify;
@@ -189,6 +190,54 @@ public void doRun_requestBatchesFilterOnClient_ok() throws Exception {
189190
assertEquals(expected, actual);
190191
}
191192

193+
@Test
194+
public void doRun_requestBatchesFilterOnClient_nullDate_success() throws Exception {
195+
final ZonedDateTime endTime =
196+
ZonedDateTime.ofInstant(Instant.ofEpochMilli(timestampInMockResponses), UTC).plusHours(1);
197+
final ZonedDateTime startTime = endTime.minusDays(7);
198+
Date lastCapturedDate = Date.from(startTime.toInstant());
199+
when(context.getArguments()).thenReturn(new ConnectorArguments("--connector", "oozie"));
200+
MemoryByteSink sink = new MemoryByteSink();
201+
stubOozieVersionsCall();
202+
server.stubFor(
203+
get(urlEqualTo("/v2/jobs?filter=sortby%3DendTime%3B&jobtype=wf&offset=1&len=1000"))
204+
.willReturn(
205+
okJsonWithBodyFile("oozie/jobs-one-item-template.json")
206+
.withTransformers("response-template")
207+
.withTransformerParameter(
208+
// filter out this job because endTime is null (job is in progress)
209+
"endTime", null)));
210+
server.stubFor(
211+
get(urlEqualTo("/v2/jobs?filter=sortby%3DendTime%3B&jobtype=wf&offset=2&len=1000"))
212+
.willReturn(
213+
okJsonWithBodyFile("oozie/jobs-one-item-template.json")
214+
.withTransformers("response-template")
215+
.withTransformerParameter(
216+
// include this job
217+
"endTime", JsonUtils.formatDateRfc822(lastCapturedDate))));
218+
server.stubFor(
219+
get(urlEqualTo("/v2/jobs?filter=sortby%3DendTime%3B&jobtype=wf&offset=3&len=1000"))
220+
.willReturn(
221+
okJsonWithBodyFile("oozie/jobs-one-item-template.json")
222+
.withTransformers("response-template")
223+
.withTransformerParameter(
224+
// filter out this job, because out of range
225+
// before start
226+
"endTime",
227+
JsonUtils.formatDateRfc822(
228+
Date.from(startTime.minusSeconds(1).toInstant())))));
229+
230+
OozieWorkflowJobsTask task = new OozieWorkflowJobsTask(startTime, endTime);
231+
232+
// Act
233+
task.doRun(context, sink, new OozieHandle(oozieClient));
234+
235+
// Assert
236+
String actual = sink.getContent();
237+
String expected = readFileAsString("/oozie/expected-jobs-one-job-from-template.csv");
238+
assertEquals(expected, actual);
239+
}
240+
192241
@Test
193242
public void doRun_requestBatchesUntilEmptyResponse_ok() throws Exception {
194243
when(context.getArguments()).thenReturn(new ConnectorArguments("--connector", "oozie"));
@@ -284,6 +333,14 @@ public void getJobEndTime_success() throws Exception {
284333
verifyNoMoreInteractions(job);
285334
}
286335

336+
@Test
337+
public void getJobEndTime_nullable() {
338+
OozieWorkflowJobsTask task = newOozieWorkflowJobTaskForOneDay();
339+
WorkflowJob job = mock(WorkflowJob.class);
340+
341+
assertNull("null is expected value for end time", task.getJobEndTime(job));
342+
}
343+
287344
@Test
288345
public void csvHeadersContainRequiredFields() {
289346
OozieWorkflowJobsTask task = newOozieWorkflowJobTaskForOneDay();
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
acl,actions,appName,appPath,conf,consoleUrl,createdTime,endTime,externalId,group,id,lastModifiedTime,parentId,run,startTime,status,user
2+
,[],Empty workflow,,,https://oozie-host:11443/oozie?job=0000128-250317102116043-oozie-oozi-W,1741701600000,1741618860000,,,0000128-250317102116043-oozie-oozi-W,1742220060000,0000002-250307121251646-oozie-oozi-C@473,0,1742220060000,SUCCEEDED,csso_dev
3+

0 commit comments

Comments
 (0)