2016-10-22 5 views
0

Ich habe einen Spring Batch-Auftrag, der eine XML-Datei liest und in eine Datenbank schreibt. Bis heute lief alles gut. Jetzt gibt der Job jedoch ein ProgramElement-Objekt mit Nullattributen an den Prozessor zurück. Ich verwende den StaxEventItemReader und eine benutzerdefinierte Partitionierer. Irgendeine Idee, warum der Leser null Attribute zurückgibt?Spring: StaxEventItemReader Rückgabe von Objekt mit Nullwerten

EDIT: Ich sollte erwähnen, dies geschah, nachdem ich Java aktualisiert von Version 102 bis 112

Job Kontextdatei:

<?xml version="1.0" encoding="UTF-8"?> 

<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:batch="http://www.springframework.org/schema/batch" 
xmlns:task="http://www.springframework.org/schema/task" xmlns:file="http://www.springframework.org/schema/integration/file" 
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd  
http://www.springframework.org/schema/integration/file 
http://www.springframework.org/schema/integration/file/spring-integration-file.xsd 
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd 
http://www.springframework.org/schema/batch 
http://www.springframework.org/schema/batch/spring-batch.xsd 
http://www.springframework.org/schema/context 
http://www.springframework.org/schema/context/spring-context.xsd  
http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/spring-util.xsd 
http://www.springframework.org/schema/task 
http://www.springframework.org/schema/task/spring-task.xsd 
http://www.springframework.org/schema/jdbc 
http://www.springframework.org/schema/jdbc/spring-jdbc.xsd"> 

<import resource="data-source-context.xml" /> 
<import resource="job-launcher-context.xml" /> 

<batch:job id="spa_r2_data_load"> 
    <batch:step id="loadData"> 
     <batch:partition step="loadDataStep" partitioner="filePartitioner" /> 
    </batch:step> 
</batch:job> 

<batch:step id="loadDataStep"> 
    <batch:tasklet> 
     <batch:chunk reader="xmlItemReader" processor="peProcessor" 
      writer="dbWriter" commit-interval="1" /> 
    </batch:tasklet> 
    <batch:listeners> 
     <batch:listener ref="listener"/> 
    </batch:listeners> 
</batch:step> 

<bean id="listener" class="com.mason.seor.listener.FileListener" scope="step"> 
    <property name="fileName" value="#{stepExecutionContext['file.location']}"/> 
</bean> 

<bean id="filePartitioner" class="com.mason.seor.partitioner.FilePartitioner"> 
    <property name="fileLocationsProp" value="${file.location}" /> 
    <property name="fileNamesProp" value="${file.names:#{null}}" /> 
</bean> 

<bean id="xmlItemReader" class="org.springframework.batch.item.xml.StaxEventItemReader" scope="step"> 
    <property name="resource" value="#{stepExecutionContext['file.location']}" /> 
    <property name="fragmentRootElementName" value="ProgramElement" /> 
    <property name="unmarshaller"> 
     <bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> 
      <property name="classesToBeBound"> 
       <list> 
        <value>com.mason.seor.model.r2.ProgramElement</value> 
        <value>com.mason.seor.model.r2.ProgramElementFunding</value> 
       </list> 
      </property> 
     </bean> 
    </property> 
</bean> 

<bean id="peProcessor" class="com.mason.seor.processor.R2Processor" 
    scope="step"/> 

<bean id="dbWriter" 
    class="org.springframework.batch.item.database.HibernateItemWriter"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

Datei Partitioner:

package com.mason.seor.partitioner; 

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.FileOutputStream; 
import java.io.FilenameFilter; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.io.OutputStreamWriter; 
import java.io.PrintWriter; 
import java.util.HashMap; 
import java.util.Map; 

import org.apache.commons.lang3.StringUtils; 
import org.springframework.batch.core.partition.support.Partitioner; 
import org.springframework.batch.item.ExecutionContext; 

public class FilePartitioner implements Partitioner { 

String fileLocationsProp; 
String fileNamesProp; 

@Override 
public Map<String, ExecutionContext> partition(int arg0){ 

    Map<String, ExecutionContext> partitionMap = new HashMap<>(); 
    String[] fileNames; 
    if (fileNamesProp == null) { 
     File filesDir = new File(fileLocationsProp.replace("file:", "")); 
     if (!filesDir.isDirectory()) { 
      throw new IllegalStateException("HEY! " + fileLocationsProp + " is not a directory!!!!!!!"); 
     } 

     // create new filename filter 
     FilenameFilter fileNameFilter = new FilenameFilter() { 

      @Override 
      public boolean accept(File dir, String name) { 
       if(name.lastIndexOf('.')>0) 
       { 
        // get last index for '.' char 
        int lastIndex = name.lastIndexOf('.'); 

        // get extension 
        String str = name.substring(lastIndex); 

        // match path name extension 
        if(str.equals(".xml")) 
        { 
        return true; 
        } 
       } 
       return false; 
      } 
     }; 

     fileNames = filesDir.list(fileNameFilter); 
    } else { 
     fileNames = fileNamesProp.split(","); 
    } 
    int counter = 0; 

    for (String fileName : fileNames) { 

     //trimXmlTags(fileLocationsProp,fileName); 

     ExecutionContext context = new ExecutionContext(); 
     context.put("file.location", fileLocationsProp + fileName); 
     context.put("file.name", fileName); 
     counter++; 
     partitionMap.put("file" + counter, context); 
    } 

    return partitionMap; 
} 

private void trimXmlTags(String fileLocation, String fileName){ 
     File xml = new File(fileLocation.replace("file:", "")+fileName); 
     String charset = "UTF-8"; 
     // need to get rid of these prefixes for the XML tags and attributes 
     String[] delete = {"r2:",":r2"}; 
     String[] replace = {"",""}; 
     // we don't need these lines 
     String throwOut = "jb:"; 
     try { 
      File temp = File.createTempFile("temp", ".xml", xml.getParentFile()); 

      //open file for reading 
      BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(xml), charset)); 
      //open temp file for writing 
      PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(temp), charset)); 

      for (String line; (line = reader.readLine()) != null;) { 
       line = StringUtils.replaceEach(line, delete, replace); 
       if(!line.contains(throwOut)){ 
        writer.println(line); 
       } 
      } 

      reader.close(); 
      writer.close(); 

      xml.delete(); 
      temp.renameTo(xml); 


     } catch (IOException e) { 
      System.out.println("file location not found: "+xml.getParentFile()); 
      System.exit(1); 
     } 
} 

public void setFileLocationsProp(String fileLocationsProp) { 
    this.fileLocationsProp = fileLocationsProp; 
} 

public void setFileNamesProp(String fileNamesProp) { 
    this.fileNamesProp = fileNamesProp; 
} 

} 

ProgramElement-Klasse:

package com.mason.seor.model.r2; 

import java.util.Date; 

import javax.xml.bind.annotation.XmlAttribute; 
import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlRootElement; 
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 

import com.mason.seor.data.SubmissionDateConverter; 

@XmlRootElement(name = "ProgramElement",  namespace="http://www.dtic.mil/comptroller/xml/schema/022009/r2") 
public class ProgramElement { 

String monetaryUnit; 
String programElementNumber; 
String programElementTitle; 
Integer r1LineNumber; 
Integer budgetYear; 
String budgetCycle; 
Date submissionDate; 
String serviceAgencyName; 
String AppropriationCode; 
String appropriationName; 
Integer budgetActivityNumber; 
String budgetActivityTitle; 
ProgramElementFunding programElementFunding; 

@XmlAttribute(name = "MonetaryUnit") 
public String getMonetaryUnit() { 
    return monetaryUnit; 
} 

public void setMonetaryUnit(String monetaryUnit) { 
    this.monetaryUnit = monetaryUnit; 
} 

@XmlElement(name = "ProgramElementNumber") 
public String getProgramElementNumber() { 
    return programElementNumber; 
} 

public void setProgramElementNumber(String programelementNumber) { 
    this.programElementNumber = programelementNumber; 
} 

@XmlElement(name = "ProgramElementTitle") 
public String getProgramElementTitle() { 
    return programElementTitle; 
} 

public void setProgramElementTitle(String programElementTitle) { 
    this.programElementTitle = programElementTitle; 
} 

@XmlElement(name = "R1LineNumber") 
public Integer getR1LineNumber() { 
    return r1LineNumber; 
} 

public void setR1LineNumber(Integer r1LineNumber) { 
    this.r1LineNumber = r1LineNumber; 
} 

@XmlElement(name = "BudgetYear") 
public Integer getBudgetYear() { 
    return budgetYear; 
} 

public void setBudgetYear(Integer budgetYear) { 
    this.budgetYear = budgetYear; 
} 

@XmlElement(name = "BudgetCycle") 
public String getBudgetCycle() { 
    return budgetCycle; 
} 

public void setBudgetCycle(String budgetCycle) { 
    this.budgetCycle = budgetCycle; 
} 

@XmlJavaTypeAdapter(type = Date.class, value = SubmissionDateConverter.class) 
@XmlElement(name = "SubmissionDate") 
public Date getSubmissionDate() { 
    return submissionDate; 
} 

public void setSubmissionDate(Date submissionDate) { 
    this.submissionDate = submissionDate; 
} 

@XmlElement(name = "ServiceAgencyName") 
public String getServiceAgencyName() { 
    return serviceAgencyName; 
} 

public void setServiceAgencyName(String serviceAgencyName) { 
    this.serviceAgencyName = serviceAgencyName; 
} 

@XmlElement(name = "AppropriationCode") 
public String getAppropriationCode() { 
    return AppropriationCode; 
} 

public void setAppropriationCode(String appropriationCode) { 
    AppropriationCode = appropriationCode; 
} 

@XmlElement(name = "AppropriationName") 
public String getAppropriationName() { 
    return appropriationName; 
} 

public void setAppropriationName(String appropriationName) { 
    this.appropriationName = appropriationName; 
} 

@XmlElement(name = "BudgetActivityNumber") 
public Integer getBudgetActivityNumber() { 
    return budgetActivityNumber; 
} 

public void setBudgetActivityNumber(Integer budgetActivityNumber) { 
    this.budgetActivityNumber = budgetActivityNumber; 
} 

@XmlElement(name = "BudgetActivityTitle") 
public String getBudgetActivityTitle() { 
    return budgetActivityTitle; 
} 

public void setBudgetActivityTitle(String budgetActivityTitle) { 
    this.budgetActivityTitle = budgetActivityTitle; 
} 

@XmlElement(name = "ProgramElementFunding") 
public ProgramElementFunding getProgramElementFunding() { 
    return programElementFunding; 
} 

public void setProgramElementFunding(ProgramElementFunding programElementFunding) { 
    this.programElementFunding = programElementFunding; 
} 

} 

ProgramElementFunding Klasse:

package com.mason.seor.model.r2; 

import javax.xml.bind.annotation.XmlElement; 
import javax.xml.bind.annotation.XmlType; 

@XmlType(name = "ProgramElementFunding") 
public class ProgramElementFunding { 

Double priorYear; 
Double currentYear; 
Double budgetYearOne; 
Double budgetYearOneBase; 
Double budgetYearTwo; 
Double budgetYearThree; 
Double budgetYearFour; 
Double budgetYearFive; 

@XmlElement(name = "PriorYear") 
public Double getPriorYear() { 
    return priorYear; 
} 
public void setPriorYear(Double priorYear) { 
    this.priorYear = priorYear; 
} 
@XmlElement(name = "CurrentYear") 
public Double getCurrentYear() { 
    return currentYear; 
} 
public void setCurrentYear(Double currentYear) { 
    this.currentYear = currentYear; 
} 
@XmlElement(name = "BudgetYearOne") 
public Double getBudgetYearOne() { 
    return budgetYearOne; 
} 
public void setBudgetYearOne(Double budgetYearOne) { 
    this.budgetYearOne = budgetYearOne; 
} 
@XmlElement(name = "BudgetYearOneBase") 
public Double getBudgetYearOneBase() { 
    return budgetYearOneBase; 
} 
public void setBudgetYearOneBase(Double budgetYearOneBase) { 
    this.budgetYearOneBase = budgetYearOneBase; 
} 
@XmlElement(name = "BudgetYearTwo") 
public Double getBudgetYearTwo() { 
    return budgetYearTwo; 
} 
public void setBudgetYearTwo(Double budgetYearTwo) { 
    this.budgetYearTwo = budgetYearTwo; 
} 
@XmlElement(name = "BudgetYearThree") 
public Double getBudgetYearThree() { 
    return budgetYearThree; 
} 
public void setBudgetYearThree(Double budgetYearThree) { 
    this.budgetYearThree = budgetYearThree; 
} 
@XmlElement(name = "BudgetYearFour") 
public Double getBudgetYearFour() { 
    return budgetYearFour; 
} 
public void setBudgetYearFour(Double budgetYearFour) { 
    this.budgetYearFour = budgetYearFour; 
} 
@XmlElement(name = "BudgetYearFive") 
public Double getBudgetYearFive() { 
    return budgetYearFive; 
} 
public void setBudgetYearFive(Double budgetYearFive) { 
    this.budgetYearFive = budgetYearFive; 
} 



} 

XML-Beispiel:

<?xml version="1.0" encoding="UTF-8"?> 
<ProgramElementList xmlns="http://www.dtic.mil/comptroller/xml/schema/022009/r2" targetSchemaVersion="1.0"> 
<ProgramElement monetaryUnit="Millions" classification="UNCLASSIFIED"> 
    <ProgramElementNumber>0601110D8Z</ProgramElementNumber> 
    <ProgramElementTitle>Basic Research Initiatives</ProgramElementTitle> 
    <R1LineNumber>3</R1LineNumber> 
    <BudgetYear>2017</BudgetYear> 
    <BudgetCycle>PB</BudgetCycle> 
    <SubmissionDate>2016-02</SubmissionDate> 
    <ServiceAgencyName>Office of the Secretary Of Defense</ServiceAgencyName> 
    <AppropriationCode>0400</AppropriationCode> 
    <AppropriationName>Research, Development, Test Evaluation, Defense-Wide</AppropriationName> 
    <BudgetActivityNumber>1</BudgetActivityNumber> 
    <BudgetActivityTitle>Basic Research</BudgetActivityTitle> 
    <ProgramElementFunding> 
     <PriorYear>41.054</PriorYear> 
     <CurrentYear>71.940</CurrentYear> 
     <BudgetYearOne>36.654</BudgetYearOne> 
     <BudgetYearOneBase>36.654</BudgetYearOneBase> 
     <BudgetYearTwo>40.649</BudgetYearTwo> 
     <BudgetYearThree>42.988</BudgetYearThree> 
     <BudgetYearFour>45.607</BudgetYearFour> 
     <BudgetYearFive>46.500</BudgetYearFive> 
     <CostToComplete>Continuing</CostToComplete> 
     <TotalCost>Continuing</TotalCost> 
    </ProgramElementFunding> 
</ProgramElement> 

+1

Wenn Sie die Lösung Upgrade von Ihrem bearbeiten als neue Antwort und Zeichen gefunden und akzeptiert –

+0

@LucaBassoRicci gemacht, danke! –

Antwort

0

Offenbar war das Problem mit dem Namensraum innerhalb des XML; Aus irgendeinem Grund wurde der Namespace unzugänglich, und ich vermute, dass der Leser dadurch eine Fehlfunktion hatte. Ich habe um diese durch eine benutzerdefinierte Implementierung des XStreamMarshaller mit:

How to ignore namespace when unmarshalling XML file

Verwandte Themen