Skip to content

[bq] use generic spring-javaformat #181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions spring-batch-bigquery/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
</execution>
</executions>
</plugin>

<!-- Run tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Expand All @@ -149,6 +150,7 @@
</includes>
</configuration>
</plugin>

<!-- Generates a flattened version of the pom.xml, used instead of the original -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
Expand Down Expand Up @@ -177,6 +179,21 @@
</execution>
</executions>
</plugin>

<!-- Formatting -->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<inherited>true</inherited>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@
/**
* BigQuery {@link ItemReader} that accepts simple query as the input.
* <p>
* Internally BigQuery Java library creates a {@link com.google.cloud.bigquery.JobConfiguration.Type#QUERY} job.
* Internally BigQuery Java library creates a
* {@link com.google.cloud.bigquery.JobConfiguration.Type#QUERY} job.
* <p>
* Which means that result is coming asynchronously.
* <p>
* Also, worth mentioning that you should take into account concurrency limits.
Expand All @@ -41,71 +43,76 @@
* @param <T> your DTO type
* @author Volodymyr Perebykivskyi
* @since 0.2.0
* @see <a href="https://cloud.google.com/bigquery/docs/running-queries#queries">Interactive queries</a>
* @see <a href="https://cloud.google.com/bigquery/docs/running-queries#batch">Batch queries</a>
* @see <a href="https://cloud.google.com/bigquery/quotas#concurrent_rate_interactive_queries">Concurrency limits</a>
* @see <a href=
* "https://cloud.google.com/bigquery/docs/running-queries#queries">Interactive
* queries</a>
* @see <a href="https://cloud.google.com/bigquery/docs/running-queries#batch">Batch
* queries</a>
* @see <a href=
* "https://cloud.google.com/bigquery/quotas#concurrent_rate_interactive_queries">Concurrency
* limits</a>
*/
public class BigQueryQueryItemReader<T> implements ItemReader<T>, InitializingBean {

private final Log logger = LogFactory.getLog(getClass());

private BigQuery bigQuery;
private Converter<FieldValueList, T> rowMapper;
private QueryJobConfiguration jobConfiguration;
private Iterator<FieldValueList> iterator;

/**
* BigQuery service, responsible for API calls.
*
* @param bigQuery BigQuery service
*/
public void setBigQuery(BigQuery bigQuery) {
this.bigQuery = bigQuery;
}

/**
* Row mapper which transforms single BigQuery row into a desired type.
*
* @param rowMapper your row mapper
*/
public void setRowMapper(Converter<FieldValueList, T> rowMapper) {
this.rowMapper = rowMapper;
}

/**
* Specifies query to run, destination table, etc.
*
* @param jobConfiguration BigQuery job configuration
*/
public void setJobConfiguration(QueryJobConfiguration jobConfiguration) {
this.jobConfiguration = jobConfiguration;
}

@Override
public T read() throws Exception {
if (iterator == null) {
doOpen();
}

if (logger.isDebugEnabled()) {
logger.debug("Reading next element");
}

return iterator.hasNext() ? rowMapper.convert(iterator.next()) : null;
}

private void doOpen() throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Executing query");
}
iterator = bigQuery.query(jobConfiguration).getValues().iterator();
}

@Override
public void afterPropertiesSet() {
Assert.notNull(this.bigQuery, "BigQuery service must be provided");
Assert.notNull(this.rowMapper, "Row mapper must be provided");
Assert.notNull(this.jobConfiguration, "Job configuration must be provided");
}
private final Log logger = LogFactory.getLog(getClass());

private BigQuery bigQuery;

private Converter<FieldValueList, T> rowMapper;

private QueryJobConfiguration jobConfiguration;

private Iterator<FieldValueList> iterator;

/**
* BigQuery service, responsible for API calls.
* @param bigQuery BigQuery service
*/
public void setBigQuery(final BigQuery bigQuery) {
this.bigQuery = bigQuery;
}

/**
* Row mapper which transforms single BigQuery row into a desired type.
* @param rowMapper your row mapper
*/
public void setRowMapper(final Converter<FieldValueList, T> rowMapper) {
this.rowMapper = rowMapper;
}

/**
* Specifies query to run, destination table, etc.
* @param jobConfiguration BigQuery job configuration
*/
public void setJobConfiguration(final QueryJobConfiguration jobConfiguration) {
this.jobConfiguration = jobConfiguration;
}

@Override
public T read() throws Exception {
if (iterator == null) {
doOpen();
}

if (logger.isDebugEnabled()) {
logger.debug("Reading next element");
}

return iterator.hasNext() ? rowMapper.convert(iterator.next()) : null;
}

private void doOpen() throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Executing query");
}
iterator = bigQuery.query(jobConfiguration).getValues().iterator();
}

@Override
public void afterPropertiesSet() {
Assert.notNull(this.bigQuery, "BigQuery service must be provided");
Assert.notNull(this.rowMapper, "Row mapper must be provided");
Assert.notNull(this.jobConfiguration, "Job configuration must be provided");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,107 +31,109 @@
* @param <T> your DTO type
* @author Volodymyr Perebykivskyi
* @since 0.2.0
* @see <a href="https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-bigquery/src/test/java/org/springframework/batch/extensions/bigquery/unit/reader/builder/BigQueryInteractiveQueryItemReaderBuilderTests.java">Examples</a>
* @see <a href="https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-bigquery/src/test/java/org/springframework/batch/extensions/bigquery/unit/reader/builder/BigQueryBatchQueryItemReaderBuilderTests.java">Examples</a>
* @see <a href=
* "https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-bigquery/src/test/java/org/springframework/batch/extensions/bigquery/unit/reader/builder/BigQueryInteractiveQueryItemReaderBuilderTests.java">Examples</a>
* @see <a href=
* "https://github.com/spring-projects/spring-batch-extensions/tree/main/spring-batch-bigquery/src/test/java/org/springframework/batch/extensions/bigquery/unit/reader/builder/BigQueryBatchQueryItemReaderBuilderTests.java">Examples</a>
*/
public class BigQueryQueryItemReaderBuilder<T> {

private BigQuery bigQuery;
private String query;
private Converter<FieldValueList, T> rowMapper;
private QueryJobConfiguration jobConfiguration;
private Class<T> targetType;

/**
* BigQuery service, responsible for API calls.
*
* @param bigQuery BigQuery service
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setBigQuery(BigQuery)
*/
public BigQueryQueryItemReaderBuilder<T> bigQuery(final BigQuery bigQuery) {
this.bigQuery = bigQuery;
return this;
}

/**
* Schema of the query: {@code SELECT <column> FROM <dataset>.<table>}.
* <p>
* It is really recommended to use {@code LIMIT n}
* because BigQuery charges you for the amount of data that is being processed.
*
* @param query your query to run
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setJobConfiguration(QueryJobConfiguration)
*/
public BigQueryQueryItemReaderBuilder<T> query(final String query) {
this.query = query;
return this;
}

/**
* Row mapper which transforms single BigQuery row into a desired type.
*
* @param rowMapper your row mapper
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setRowMapper(Converter)
*/
public BigQueryQueryItemReaderBuilder<T> rowMapper(final Converter<FieldValueList, T> rowMapper) {
this.rowMapper = rowMapper;
return this;
}

/**
* Specifies query to run, destination table, etc.
*
* @param jobConfiguration BigQuery job configuration
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setJobConfiguration(QueryJobConfiguration)
*/
public BigQueryQueryItemReaderBuilder<T> jobConfiguration(final QueryJobConfiguration jobConfiguration) {
this.jobConfiguration = jobConfiguration;
return this;
}

/**
* Specifies a target type which will be used as a result.
* Only needed when {@link BigQueryQueryItemReaderBuilder#rowMapper} is not provided.
* Take into account that only {@link Class#isRecord()} supported.
*
* @param targetType a {@link Class} that represent desired type
* @return {@link BigQueryQueryItemReaderBuilder}
*/
public BigQueryQueryItemReaderBuilder<T> targetType(final Class<T> targetType) {
this.targetType = targetType;
return this;
}

/**
* Please remember about {@link BigQueryQueryItemReader#afterPropertiesSet()}.
*
* @return {@link BigQueryQueryItemReader}
*/
public BigQueryQueryItemReader<T> build() {
final BigQueryQueryItemReader<T> reader = new BigQueryQueryItemReader<>();

reader.setBigQuery(this.bigQuery == null ? BigQueryOptions.getDefaultInstance().getService() : this.bigQuery);

if (this.rowMapper == null) {
Assert.notNull(this.targetType, "No target type provided");
Assert.isTrue(this.targetType.isRecord(), "Only Java record supported");
reader.setRowMapper(new RecordMapper<T>().generateMapper(this.targetType));
} else {
reader.setRowMapper(this.rowMapper);
}

if (this.jobConfiguration == null) {
Assert.isTrue(StringUtils.hasText(this.query), "No query provided");
reader.setJobConfiguration(QueryJobConfiguration.newBuilder(this.query).build());
} else {
reader.setJobConfiguration(this.jobConfiguration);
}

return reader;
}
private BigQuery bigQuery;

private String query;

private Converter<FieldValueList, T> rowMapper;

private QueryJobConfiguration jobConfiguration;

private Class<T> targetType;

/**
* BigQuery service, responsible for API calls.
* @param bigQuery BigQuery service
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setBigQuery(BigQuery)
*/
public BigQueryQueryItemReaderBuilder<T> bigQuery(final BigQuery bigQuery) {
this.bigQuery = bigQuery;
return this;
}

/**
* Schema of the query: {@code SELECT column FROM dataset.table}.
* <p>
* It is really recommended to use {@code LIMIT n} because BigQuery charges you for
* the amount of data that is being processed.
* @param query your query to run
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setJobConfiguration(QueryJobConfiguration)
*/
public BigQueryQueryItemReaderBuilder<T> query(final String query) {
this.query = query;
return this;
}

/**
* Row mapper which transforms single BigQuery row into a desired type.
* @param rowMapper your row mapper
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setRowMapper(Converter)
*/
public BigQueryQueryItemReaderBuilder<T> rowMapper(final Converter<FieldValueList, T> rowMapper) {
this.rowMapper = rowMapper;
return this;
}

/**
* Specifies query to run, destination table, etc.
* @param jobConfiguration BigQuery job configuration
* @return {@link BigQueryQueryItemReaderBuilder}
* @see BigQueryQueryItemReader#setJobConfiguration(QueryJobConfiguration)
*/
public BigQueryQueryItemReaderBuilder<T> jobConfiguration(final QueryJobConfiguration jobConfiguration) {
this.jobConfiguration = jobConfiguration;
return this;
}

/**
* Specifies a target type which will be used as a result. Only needed when
* {@link BigQueryQueryItemReaderBuilder#rowMapper} is not provided. Take into account
* that only {@link Class#isRecord()} supported.
* @param targetType a {@link Class} that represent desired type
* @return {@link BigQueryQueryItemReaderBuilder}
*/
public BigQueryQueryItemReaderBuilder<T> targetType(final Class<T> targetType) {
this.targetType = targetType;
return this;
}

/**
* Please remember about {@link BigQueryQueryItemReader#afterPropertiesSet()}.
* @return {@link BigQueryQueryItemReader}
*/
public BigQueryQueryItemReader<T> build() {
final BigQueryQueryItemReader<T> reader = new BigQueryQueryItemReader<>();

reader.setBigQuery(this.bigQuery == null ? BigQueryOptions.getDefaultInstance().getService() : this.bigQuery);

if (this.rowMapper == null) {
Assert.notNull(this.targetType, "No target type provided");
Assert.isTrue(this.targetType.isRecord(), "Only Java record supported");
reader.setRowMapper(new RecordMapper<T>().generateMapper(this.targetType));
}
else {
reader.setRowMapper(this.rowMapper);
}

if (this.jobConfiguration == null) {
Assert.isTrue(StringUtils.hasText(this.query), "No query provided");
reader.setJobConfiguration(QueryJobConfiguration.newBuilder(this.query).build());
}
else {
reader.setJobConfiguration(this.jobConfiguration);
}

return reader;
}

}
Loading