From: arne@vajhoej.dk   
      
   On 3/28/2025 8:51 AM, Arne Vajhøj wrote:   
   > On 3/18/2025 3:51 PM, Arne Vajhøj wrote:   
   >> I am happy to report that Spring Batch 4.3 works fine on   
   >> VMS x86-64 (and probably also on VMS Itanium, but not on   
   >> VMS Alpha due to too old Java version).   
   >>   
   >> For database, XML, JSON and CSV the following jar files:   
   >   
   >> The code and configuration is the same as on any other platform.   
   >   
   > Spring Batch can read/write from/to relational databases and a few NoSQL   
   > databases   
   > as well: MongoDB, Neo4J and Redis.   
   >   
   > Obviously it does not read/write VMS index-sequential files out of the box.   
   >   
   > But since I happen to have a library allowing JVM languages to access VMS   
   > index-sequential files, then creating a wrapper allowing Sping Batch to   
   > access   
   > them was tempting.   
   >   
   > So I did.   
   >   
   > First the simple model with only one index-sequential file.   
      
   The more tricky case is multiple index-sequential files similar to   
   one-to-many   
   relations in relational databases.   
      
   (index-sequentiel files allow for arrays within records, but that is not   
   always   
   possible to utilize due to the 32 KB limit)   
      
   import java.lang.reflect.Method;   
      
   import dk.vajhoej.isam.IsamSource;   
      
   public class ReaderSecondarySource {   
    private String primaryKey; // name of key in primary source used to   
   lookup in secondary source   
    private String primaryList; // name of list in primary source   
   containing records from secondary source   
    private Class type; // type of records in secondary source   
    private int index; // index of key in secondary source used to   
   lookup in secondary source   
    private IsamSource source; // secondary source   
    private Method primaryKeyGetter;   
    private Method primaryListGetter;   
    public String getPrimaryKey() {   
    return primaryKey;   
    }   
    public void setPrimaryKey(String primaryKey) {   
    this.primaryKey = primaryKey;   
    }   
    public String getPrimaryList() {   
    return primaryList;   
    }   
    public void setPrimaryList(String primaryList) {   
    this.primaryList = primaryList;   
    }   
    public Class getType() {   
    return type;   
    }   
    public void setType(Class type) {   
    this.type = type;   
    }   
    public int getIndex() {   
    return index;   
    }   
    public void setIndex(int index) {   
    this.index = index;   
    }   
    public IsamSource getSource() {   
    return source;   
    }   
    public void setSource(IsamSource source) {   
    this.source = source;   
    }   
    public Method getPrimaryKeyGetter() {   
    return primaryKeyGetter;   
    }   
    public void setPrimaryKeyGetter(Method primaryKeyGetter) {   
    this.primaryKeyGetter = primaryKeyGetter;   
    }   
    public Method getPrimaryListGetter() {   
    return primaryListGetter;   
    }   
    public void setPrimaryListGetter(Method primaryListGetter) {   
    this.primaryListGetter = primaryListGetter;   
    }   
   }   
      
   import java.lang.reflect.Method;   
   import java.util.List;   
      
   import org.springframework.batch.item.ExecutionContext;   
   import org.springframework.batch.item.NonTransientResourceException;   
   import org.springframework.batch.item.ParseException;   
   import org.springframework.batch.item.UnexpectedInputException;   
   import org.springframework.batch.item.support.AbstractItemStreamItemReader;   
      
   import dk.vajhoej.isam.IsamException;   
   import dk.vajhoej.isam.IsamResult;   
   import dk.vajhoej.isam.IsamSource;   
   import dk.vajhoej.isam.Key;   
   import dk.vajhoej.isam.KeyInfoArrayCache;   
   import dk.vajhoej.record.RecordException;   
      
   public class MultiIsamItemReader extends   
   AbstractItemStreamItemReader {   
    private IsamSource primarySource;   
    private Class type;   
    private List secondarySources;   
    private IsamResult result;   
    public IsamSource getPrimarySource() {   
    return primarySource;   
    }   
    public void setPrimarySource(IsamSource primarySource) {   
    this.primarySource = primarySource;   
    }   
    public Class getType() {   
    return type;   
    }   
    public void setType(Class type) {   
    this.type = type;   
    }   
    public List getSecondarySources() {   
    return secondarySources;   
    }   
    public void setSecondarySources(List   
   secondarySources) {   
    this.secondarySources = secondarySources;   
    }   
    private Method getGetter(String fldnam) {   
    try {   
    return type.getMethod("get" + fldnam.substring(0,   
   1).toUpperCase() + fldnam.substring(1));   
    } catch (NoSuchMethodException e) {   
    throw new RuntimeException(e);   
    } catch (SecurityException e) {   
    throw new RuntimeException(e);   
    }   
    }   
    @Override   
    public void open(ExecutionContext ec) {   
    try {   
    result = primarySource.readStart(type);   
    for(ReaderSecondarySource> src2 : secondarySources) {   
    src2.setPrimaryKeyGetter(getGetter(src2.getPrimaryKey()));   
      
   src2.setPrimaryListGetter(getGetter(src2.getPrimaryList()));   
    }   
    } catch (IsamException e) {   
    throw new RuntimeException(e);   
    } catch (RecordException e) {   
    throw new RuntimeException(e);   
    }   
    }   
    @Override   
    public T read() throws Exception, UnexpectedInputException,   
   ParseException, NonTransientResourceException {   
    if(result.read()) {   
    T o = result.current();   
    for(ReaderSecondarySource src2 : secondarySources) {   
    int keyix = src2.getIndex();   
    Comparable keyval =   
   (Comparable)src2.getPrimaryKeyGetter().invoke(o);   
    List lst2 = (List)src2.getPrimaryListGetter().invoke(o);   
    Class t = src2.getType();   
    IsamSource is = src2.getSource();   
    IsamResult ir = is.readGE(t, new Key(keyix, keyval));   
    while(ir.read()) {   
    Object o2 = ir.current();   
    Comparable keyval2 =   
   (Comparable)KeyInfoArrayCache.analyze(t)[src2.getIndex()].getField().get(o2);   
    if(keyval.compareTo(keyval2) == 0) {   
    lst2.add(o2);   
    } else {   
    break;   
    }   
    }   
    }   
    return o;   
    } else {   
    return null;   
    }   
    }   
    @Override   
    public void close() {   
    try {   
    result.close();   
    primarySource.close();   
    for(ReaderSecondarySource src2 : secondarySources) {   
    src2.getSource().close();   
    }   
    } catch (IsamException e) {   
    throw new RuntimeException(e);   
    }   
    }   
   }   
      
      
      
   [continued in next message]   
      
   --- SoupGate-DOS v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|