Java tutorial
/* * Copyright (c) 2014 Red Hat, Inc. and/or its affiliates. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Cheng Fang - Initial API and implementation */ package org.jberet.support.io; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.Writer; import java.lang.reflect.Type; import java.util.Map; import java.util.Properties; import java.util.concurrent.TimeUnit; import javax.batch.operations.JobOperator; import javax.batch.runtime.BatchRuntime; import javax.batch.runtime.BatchStatus; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.io.IOContext; import com.fasterxml.jackson.core.io.InputDecorator; import com.fasterxml.jackson.core.io.OutputDecorator; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler; import org.jberet.runtime.JobExecutionImpl; import org.junit.Assert; import org.junit.Test; /** * A test class that reads json resource into java object and write out to json format. */ public final class JsonItemReaderTest { static final String jobName = "org.jberet.support.io.JsonItemReaderTest"; private final JobOperator jobOperator = BatchRuntime.getJobOperator(); static final String movieJson = "movies-2012.json"; static final String movieJsonUnknownProperty = "movies-2012-unknown-properties.json"; static final String widgetJson = "widget.json"; static final String githubJson = "https://api.github.com/users/chengfang/repos"; static final String widgetExpect1 = "\"widget\", \"debug\", \"window\", \"title\", " + "\"Sample Konfabulator Widget\", \"name\", \"main_window\", \"width\"," + "500, \"height\", \"image\", \"src\", \"Images/Sun.png\", \"sun1\", \"hOffset\", 250," + "\"vOffset\", \"alignment\", \"center\", \"text\", \"data\", \"Click Here\", \"size\"," + "36, \"style\", \"bold\", \"text1\", \"onMouseUp\", " + "\"sun1.opacity = (sun1.opacity / 100) * 90;\""; static final String widgetExpect2 = "\"Two Widget\", \"two_window\", \"Images/Two.png\""; static final String widgetExpect3 = "\"Three Widget\", \"three_window\", \"Images/Three.png\""; static final String widgetForbidFrom1 = "Sample Konfabulator Widget, main_window, Images/Sun.png"; private String jsonGeneratorFeatures; private String deserializationProblemHandlers; private String customDataTypeModules; //https://issues.jboss.org/browse/JBERET-44 //no transaction started after a chunk where no data is written. //the ItemProcessor in this test is configured to filter out all items so there is always no data to write out. //when a new chunk is started, TransactionManager should also begin a new tx. @Test public void testMovieFilterProcessor() throws Exception { final String filtering = "filtering"; System.setProperty(filtering, "true"); testReadWrite0(movieJson, "testMovieFilterProcessor.out", "1", "15", Movie.class, null, null, BatchStatus.COMPLETED); System.clearProperty(filtering); } @Test public void testBeanTypeGithubJson1_999() throws Exception { testReadWrite0(githubJson, "testBeanTypeGithubJson1_999.out", "1", "999", GithubData.class, null, null, BatchStatus.COMPLETED); } @Test public void testBeanTypeGithubJson1() throws Exception { testReadWrite0(githubJson, "testBeanTypeGithubJson1.out", "1", "1", GithubData.class, null, null, BatchStatus.COMPLETED); } @Test public void testBeanTypeGithubJson2_3() throws Exception { testReadWrite0(githubJson, "testBeanTypeGithubJson2_3.out", "2", "3", GithubData.class, null, null, BatchStatus.COMPLETED); } @Test public void testNodeTypeGithubJson() throws Exception { testReadWrite0(githubJson, "testNodeTypeGithubJson.out", null, null, JsonNode.class, null, null, BatchStatus.COMPLETED); } @Test public void testBeanType2_4() throws Exception { jsonGeneratorFeatures = " QUOTE_FIELD_NAMES = false , STRICT_DUPLICATE_DETECTION = false"; //rating enum is written out as index, as configured in job xml serializationFeatures property //final String forbid = MovieTest.forbid2_4 + ", \"rank\", \"tit\", \"grs\", \"opn\", PG13"; final String forbid = MovieTest.forbid2_4 + ", PG13"; testReadWrite0(movieJson, "testBeanType2_4.out", "2", "4", Movie.class, MovieTest.expect2_4, forbid, BatchStatus.COMPLETED); jsonGeneratorFeatures = null; } @Test public void testJsonNodeType2_4() throws Exception { testReadWrite0(movieJson, "testJsonNodeType2_4.out", "2", "4", JsonNode.class, MovieTest.expect2_4, MovieTest.forbid2_4, BatchStatus.COMPLETED); } @Test public void testBeanTypeFull() throws Exception { testReadWrite0(movieJson, "testBeanTypeFull.out", null, null, Movie.class, MovieTest.expectFull, null, BatchStatus.COMPLETED); } @Test public void testBeanTypeJodaFull() throws Exception { customDataTypeModules = "com.fasterxml.jackson.datatype.joda.JodaModule, com.fasterxml.jackson.datatype.jdk7.Jdk7Module"; testReadWrite0(movieJson, "testBeanTypeJodaFull.out", null, null, MovieWithJoda.class, MovieTest.expectFull, null, BatchStatus.COMPLETED); customDataTypeModules = null; } @Test public void testMapTypeFull1_100() throws Exception { testReadWrite0(movieJson, "testMapTypeFull1_100.out", "1", "100", Map.class, MovieTest.expectFull, null, BatchStatus.COMPLETED); } @Test public void testJsonMapType1_2() throws Exception { testReadWrite0(movieJson, "testJsonMapType1_2.out", "1", "2", Map.class, MovieTest.expect1_2, MovieTest.forbid1_2, BatchStatus.COMPLETED); } @Test public void testJsonNodeTypeWidget1() throws Exception { testReadWrite0(widgetJson, "testJsonNodeTypeWidget1.out", "1", "1", JsonNode.class, widgetExpect1, widgetExpect2, BatchStatus.COMPLETED); } @Test public void testJsonNodeTypeWidget1_3() throws Exception { testReadWrite0(widgetJson, "testJsonNodeTypeWidget1_3.out", "1", "3", JsonNode.class, widgetExpect1 + ", " + widgetExpect2 + ", " + widgetExpect3, null, BatchStatus.COMPLETED); testReadWrite0(widgetJson, "testJsonNodeTypeWidget1_3.out", null, null, JsonNode.class, widgetExpect1 + ", " + widgetExpect2 + ", " + widgetExpect3, null, BatchStatus.COMPLETED); } @Test public void testMapTypeWidget2_3() throws Exception { testReadWrite0(widgetJson, "testMapTypeWidget2_3.out", "2", "3", Map.class, widgetExpect2 + ", " + widgetExpect3, widgetForbidFrom1, BatchStatus.COMPLETED); } //2 unknown properties in json file will cause the read to fail @Test public void testUnknownJsonPropertyFail1_2() throws Exception { testReadWrite0(movieJsonUnknownProperty, "testUnknownJsonPropertyFail1_2.out", "1", "2", Movie.class, MovieTest.expect1_2, MovieTest.forbid1_2, BatchStatus.FAILED); } //configured 1 problem handler for unknow property 1, not for unknown property 2, so will still fail @Test public void testUnknownJsonPropertyFail2_4() throws Exception { this.deserializationProblemHandlers = "org.jberet.support.io.JsonItemReaderTest$UnknownHandler"; testReadWrite0(movieJsonUnknownProperty, "testUnknownJsonPropertyFail2_4.out", "2", "4", Movie.class, MovieTest.expect2_4, MovieTest.forbid2_4, BatchStatus.FAILED); this.deserializationProblemHandlers = null; } //configured 2 problem handlers for both unknown properties, so the unknow properties are properly handled and the //job should complete. @Test public void testUnknownJsonProperty2_4() throws Exception { this.deserializationProblemHandlers = "org.jberet.support.io.JsonItemReaderTest$UnknownHandler, org.jberet.support.io.JsonItemReaderTest$Unknown2Handler"; testReadWrite0(movieJsonUnknownProperty, "testUnknownJsonProperty2_4.out", "2", "4", Movie.class, MovieTest.expect2_4, MovieTest.forbid2_4, BatchStatus.COMPLETED); this.deserializationProblemHandlers = null; } private void testReadWrite0(final String resource, final String writeResource, final String start, final String end, final Class<?> beanType, final String expect, final String forbid, final BatchStatus jobStatus) throws Exception { final Properties params = CsvItemReaderWriterTest.createParams(CsvProperties.BEAN_TYPE_KEY, beanType.getName()); params.setProperty(CsvProperties.RESOURCE_KEY, resource); final File writeResourceFile = new File(CsvItemReaderWriterTest.tmpdir, writeResource); params.setProperty("writeResource", writeResourceFile.getPath()); if (start != null) { params.setProperty(CsvProperties.START_KEY, start); } if (end != null) { params.setProperty(CsvProperties.END_KEY, end); } if (jsonGeneratorFeatures != null) { params.setProperty("jsonGeneratorFeatures", jsonGeneratorFeatures); } if (deserializationProblemHandlers != null) { params.setProperty("deserializationProblemHandlers", deserializationProblemHandlers); } if (customDataTypeModules != null) { params.setProperty("customDataTypeModules", customDataTypeModules); } params.setProperty(CsvProperties.HEADER_KEY, MovieTest.header); CsvItemReaderWriterTest.setRandomWriteMode(params); final long jobExecutionId = jobOperator.start(jobName, params); final JobExecutionImpl jobExecution = (JobExecutionImpl) jobOperator.getJobExecution(jobExecutionId); jobExecution.awaitTermination(CsvItemReaderWriterTest.waitTimeoutMinutes, TimeUnit.MINUTES); Assert.assertEquals(jobStatus, jobExecution.getBatchStatus()); if (jobStatus == BatchStatus.COMPLETED) { CsvItemReaderWriterTest.validate(writeResourceFile, expect, forbid); } } public static final class NoopInputDecorator extends InputDecorator { @Override public InputStream decorate(final IOContext ctxt, final InputStream in) throws IOException { System.out.printf("In decorate method of %s%n", this); return in; } @Override public InputStream decorate(final IOContext ctxt, final byte[] src, final int offset, final int length) throws IOException { System.out.printf("In decorate method of %s%n", this); return new ByteArrayInputStream(src, offset, length); } @Override public Reader decorate(final IOContext ctxt, final Reader src) throws IOException { System.out.printf("In decorate method of %s%n", this); return src; } } public static final class NoopOutputDecorator extends OutputDecorator { @Override public OutputStream decorate(final IOContext ctxt, final OutputStream out) throws IOException { System.out.printf("In decorate method of %s%n", this); return out; } @Override public Writer decorate(final IOContext ctxt, final Writer w) throws IOException { System.out.printf("In decorate method of %s%n", this); return w; } } public static final class JsonSerializer<Exception> extends com.fasterxml.jackson.databind.JsonSerializer<Exception> { @Override public void serialize(final Exception value, final JsonGenerator jgen, final SerializerProvider provider) throws IOException, JsonProcessingException { jgen.writeObject(value); } } public static final class JsonDeserializer<Exception> extends com.fasterxml.jackson.databind.JsonDeserializer<Exception> { @Override public Exception deserialize(final JsonParser jp, final DeserializationContext ctxt) throws IOException, JsonProcessingException { return jp.readValueAs(new TypeReference<Exception>() { @Override public Type getType() { return super.getType(); } @Override public int compareTo(final TypeReference<Exception> o) { return super.compareTo(o); } }); } } public static final class UnknownHandler extends DeserializationProblemHandler { @Override public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser jp, final com.fasterxml.jackson.databind.JsonDeserializer<?> deserializer, final Object beanOrClass, final String propertyName) throws IOException, JsonProcessingException { if (propertyName.equals("unknown")) { jp.skipChildren(); return true; } return false; } } public static final class Unknown2Handler extends DeserializationProblemHandler { @Override public boolean handleUnknownProperty(final DeserializationContext ctxt, final JsonParser jp, final com.fasterxml.jackson.databind.JsonDeserializer<?> deserializer, final Object beanOrClass, final String propertyName) throws IOException, JsonProcessingException { if (propertyName.equals("unknown2")) { jp.skipChildren(); return true; } return false; } } }