Page 1 of 2 12 LastLast
Results 1 to 10 of 15

Thread: some class that I needed.

  1. #1
    Join Date
    Feb 2008
    Posts
    12

    Talking some class that I needed.

    Hi. Spring Batch is great. I read it Seriously.

    I Engaged in enterprise batch working.

    when I use it on my working, I writed two abstract class.

    for above:

    /*
    * Copyright 2006-2007 the original author or authors.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    * http://www.apache.org/licenses/LICENSE-2.0
    *
    * Unless required by applicable law or agreed to in writing, software
    * distributed under the License is distributed on an "AS IS" BASIS,
    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    * See the License for the specific language governing permissions and
    * limitations under the License.
    */
    package cn.bestwiz.batch.database;

    import java.sql.SQLException;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;

    import org.springframework.batch.item.ClearFailedExceptio n;
    import org.springframework.batch.item.FlushFailedExceptio n;
    import org.springframework.batch.item.ItemWriter;
    import org.springframework.batch.item.database.ItemPrepar edStatementSetter;
    import org.springframework.batch.repeat.RepeatContext;
    import org.springframework.batch.repeat.support.RepeatSyn chronizationManager;
    import org.springframework.beans.factory.InitializingBean ;
    import org.springframework.orm.ibatis.SqlMapClientCallbac k;
    import org.springframework.orm.ibatis.SqlMapClientTemplat e;
    import org.springframework.transaction.support.Transactio nSynchronizationManager;
    import org.springframework.util.Assert;

    import com.ibatis.sqlmap.client.SqlMapExecutor;
    import com.mysql.jdbc.PreparedStatement;

    public abstract class AbstractIbatisItemWriter implements ItemWriter, InitializingBean {

    protected static final String ITEMS_PROCESSED = AbstractIbatisItemWriter.class.getName() + ".ITEMS_PROCESSED";

    private Set<Object> failed = new HashSet<Object>();

    private SqlMapClientTemplate sqlMapClientTemplate;

    public void afterPropertiesSet() throws Exception {
    Assert.notNull(sqlMapClientTemplate, "IbatisItemWriter requires an SqlMapClientTemplate.");
    }

    public void write(Object output) throws Exception {
    bindTransactionResources();
    getProcessed().add(output);
    flushIfNecessary(output);
    }

    private Set<Object> getProcessed() {
    Set processed = (Set)TransactionSynchronizationManager.getResource (ITEMS_PROCESSED);
    if (processed == null) {
    processed = Collections.EMPTY_SET;
    }
    return processed;
    }

    private void bindTransactionResources() {
    if (TransactionSynchronizationManager.hasResource(ITE MS_PROCESSED)) {
    return;
    }
    TransactionSynchronizationManager.bindResource(ITE MS_PROCESSED, new HashSet());
    }

    private void unbindTransactionResources() {
    if (!TransactionSynchronizationManager.hasResource(IT EMS_PROCESSED)) {
    return;
    }
    TransactionSynchronizationManager.unbindResource(I TEMS_PROCESSED);
    }

    private void flushIfNecessary(Object output) throws Exception {
    boolean flush;
    synchronized (failed) {
    flush = failed.contains(output);
    }
    if (flush) {
    RepeatContext context = RepeatSynchronizationManager.getContext();
    // Force early completion to commit aggressively if we encounter a
    // failed item (from a failed chunk but we don't know which one was
    // the problem).
    context.setCompleteOnly();
    // Flush now, so that if there is a failure this record can be
    // skipped.
    doFlush();
    }
    }

    private void doFlush() {
    final Set<Object> processed = getProcessed();
    try {
    if (!processed.isEmpty()) {
    sqlMapClientTemplate.execute(new SqlMapClientCallback() {

    public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
    executor.startBatch();
    for (Iterator<Object> iterator = processed.iterator(); iterator.hasNext() {
    Object item = (Object)iterator.next();
    doProcess(item);
    }
    return executor.executeBatch();
    }

    });
    }
    }
    catch (RuntimeException e) {
    synchronized (failed) {
    failed.addAll(processed);
    }
    throw e;
    }
    finally {
    getProcessed().clear();
    }
    }

    protected abstract void doProcess(Object item);

    public void clear() throws ClearFailedException {
    unbindTransactionResources();
    }

    public void flush() throws FlushFailedException {
    try {
    doFlush();
    }
    finally {
    unbindTransactionResources();
    }
    }

    }

    package cn.bestwiz.batch.database;

    import java.util.List;

    import org.springframework.batch.item.ExecutionContext;
    import org.springframework.batch.item.ExecutionContextUse rSupport;
    import org.springframework.batch.item.database.KeyCollect or;
    import org.springframework.orm.ibatis.SqlMapClientTemplat e;
    import org.springframework.util.Assert;
    import org.springframework.util.ClassUtils;

    import com.ibatis.sqlmap.client.SqlMapClient;

    public abstract class AbstractIbatisKeyCollector extends ExecutionContextUserSupport implements KeyCollector {

    private static final String RESTART_KEY = "key.index";

    private SqlMapClientTemplate sqlMapClientTemplate;

    private String drivingQuery;

    private String restartQueryId;

    public AbstractIbatisKeyCollector() {
    setName(ClassUtils.getShortName(AbstractIbatisKeyC ollector.class));
    }

    public List<Object> retrieveKeys(ExecutionContext executionContext) {
    if (executionContext.containsKey(getKey(RESTART_KEY)) ) {
    Object key = executionContext.get(getKey(RESTART_KEY));
    return getRestartQueryId(restartQueryId, key);
    }
    else {
    return getDrivingQuery(drivingQuery);
    }
    }

    protected abstract List<Object> getRestartQueryId(String restartQueryId, Object key);

    protected abstract List<Object> getDrivingQuery(String drivingQuery);

    public void updateContext(Object key, ExecutionContext executionContext) {
    Assert.notNull(key, "Key must not be null");
    Assert.notNull(executionContext, "ExecutionContext must be null");
    executionContext.put(getKey(RESTART_KEY), key);
    }

    public void afterPropertiesSet() throws Exception {
    Assert.notNull(sqlMapClientTemplate, "SqlMaperClientTemplate must not be null.");
    Assert.hasText(drivingQuery, "The DrivingQuery must not be null or empty.");
    }

    public void setSqlMapClient(SqlMapClient sqlMapClient) {
    this.sqlMapClientTemplate = new SqlMapClientTemplate();
    this.sqlMapClientTemplate.setSqlMapClient(sqlMapCl ient);
    }

    public void setDrivingQueryId(String drivingQueryId) {
    this.drivingQuery = drivingQueryId;
    }

    public void setRestartQueryId(String restartQueryId) {
    this.restartQueryId = restartQueryId;
    }

    public final SqlMapClientTemplate getSqlMapClientTemplate() {
    return sqlMapClientTemplate;
    }

    }

    I hoped that spring batch framework can provide this kind of class for us, because I need some composite, custom operator, when I worked at enterprise. Maybe, I need one input, but I use it write to three table, when I update table, it may be affected 0 rows, I need to input a row record into this table. I want to say that many enterprise batch is composite, don't write code may be Impossible. I hope provide some class that I extends it simplly, I can finished my job easily.

  2. #2
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    If you could open JIRA issues for the ibatis support that would help you track the progress (a separate issue for the writer and the key collector would be best).

    I didn't understand the composite requirement. Maybe you could elaborate a little on what you job does in more detail?

  3. #3
    Join Date
    Feb 2008
    Posts
    12

    Default

    Dave Syer, Thank you for your answers.
    I use ibatis as my orm tools, I want to declare a keyCollector. I want to write keyCollector's sql in my ibatis sqlmap's xml, but the sql need some parameters. now, the IbatisKeyCollector class only provide setDrivingQueryId(String drivingQueryId) as setting sql's method, sometimes, I need this method: setDrivingQueryId(String drivingQueryId, Map parameters), because I don't want to write sql in my java code.
    In addition, In the case, If I read a item in the ItemReader, I write the item in ItemWriter. But the writing operation don't only be a sql, it may need to update five table, now BatchSqlUpdateItemWriter provide setSql(String sql) for ItemWriter's writing operation. sometimes I need this method: abstract doSimething(). I can't decide to do any things in the method, not only a sql operation.
    Please refer to the above questions, it may be not correct. I hope that spring batch will be more Powerful.

  4. #4
    Join Date
    Feb 2008
    Posts
    12

    Default

    where can I download the spring docs api? now, I only view it online.

  5. #5
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    Quote Originally Posted by cuizuoli View Post
    where can I download the spring docs api? now, I only view it online.
    I think most people are fine with the source jars (your IDE should be able to display the javadocs from the source). If that doesn't work for you, you probably have to build the javadocs yourself from the sources.

  6. #6
    Join Date
    Jun 2005
    Posts
    4,231

    Default

    Quote Originally Posted by cuizuoli View Post
    I need this method: setDrivingQueryId(String drivingQueryId, Map parameters)
    How are you going to set the parameters? Configuration? That would be fine. I still suggest you open a JIRA issue.

    But the writing operation don't only be a sql, it may need to update five table... I can't decide to do any things in the method, not only a sql operation.
    Most people find that they can write a composite ItemWriter that delegates to other writers for cases like this. Usually there is some business logic to decide which of the 5 tables to update, so you need to write a custom item writer.

  7. #7
    Join Date
    Feb 2008
    Posts
    12

    Default

    OK, let me try it. Thank you very much.

  8. #8
    Join Date
    Oct 2008
    Posts
    18

    Default

    was a JIRA issue ever opened for the iBatis Item Reader?
    is it planned to be supported?

  9. #9
    Join Date
    Jun 2005
    Posts
    4,231

  10. #10
    Join Date
    Oct 2008
    Posts
    18

    Default

    Thanks,
    ofcourse i saw these classes but i was asking about the writer.
    i think something like cuizuoli suggested might be useful since it's leveraging
    iBatis' batch capabilities.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •