0

In am trying to persist data from an xml (below) using JPA. However everything goes fine until I get to a nested arraylist in one of the child classes. I have tried the code below and looked at several examples e.g this and this without any success. I suppose the relationship should be OnetoMany in the Instances class. I will be really glad if someone points me in the right direction. See my code snippets below: The Instances class:

@Entity 
public class Instances { 
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
public long id; 

@OneToMany (mappedBy = "instances", cascade = CascadeType.PERSIST)
protected List<Instance> instance = new ArrayList<Instance>();
public Instances(List<Instance> instance) {         
    this.instance = instance;
}    

public Instances() {
    }

public long getId() {
    return id;
}



public void setId(long id) {
    this.id = id;
}
public List<Instance> getInstance() {
    return instance;
}
public void setInstance(List<Instance> instance) {
    this.instance = instance;
}   

The Instance class :

@Entity
public class Instance {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
public long id;
@XmlElement(required = true)
@XmlSchemaType(name = "anyURI")
protected String uri;
@XmlElement(required = true)
protected String method;
protected String evidence;
protected String param;
protected String attack;
@ManyToOne
public Instances instances;

public Instance(long id, String uri, String method, String evidence, String param, String attack) {
    super();
    this.id = id;
    this.uri = uri;
    this.method = method;
    this.evidence = evidence;
    this.param = param;
    this.attack = attack;
}

public Instance() {
}

public String getUri() {
    return uri;
}


public void setUri(String value) {
    this.uri = value;
}


public String getMethod() {
    return method;
}

public void setMethod(String value) {
    this.method = value;
}


public String getEvidence() {
    return evidence;
}


public void setEvidence(String value) {
    this.evidence = value;
}


public String getParam() {
    return param;
}


public void setParam(String value) {
    this.param = value;
}


public String getAttack() {
    return attack;
}


public void setAttack(String value) {
    this.attack = value;
}

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public Instances getInstances() {
    return instances;
}
public void setInstances(Instances instances) {
    this.instances = instances;
} 

The main class:

        System.out.println("Active Scan complete");
        System.out.println(new String(api2.core.xmlreport(ZAP_API_KEY)));
        JacksonXmlModule module = new JacksonXmlModule();
        module.setDefaultUseWrapper(false);
         XmlMapper xmlMapper = new XmlMapper(module);
        OWASPZAPReport oWASPZAPReport = new OWASPZAPReport();


        oWASPZAPReport = xmlMapper.readValue(api2.core.xmlreport(ZAP_API_KEY), OWASPZAPReport.class);

        ScannerDAO.em.getTransaction().begin();
        Site site = new Site();
        site = oWASPZAPReport.getSite();
        System.out.println(site);
        Alerts al = site.getAlerts();
        System.out.println(al);
        Alertitem alertitem = new Alertitem();
        List<Alertitem> aitems = al.getAlertitem();
        for (Alertitem item : aitems) {
            Instances instances = item.getInstances();
            Instances stances = new Instances();
            List<Instance> instance = instances.getInstance();
            Instance instancer = new Instance();
            for (Instance inst : instance) {
                instancer.setAttack(inst.getAttack());
                instancer.setUri(inst.getUri());
                instancer.setEvidence(inst.getEvidence());
                instancer.setParam(inst.getParam());
                instancer.setMethod(inst.getMethod());                  
            }
            ScannerDAO.em.persist(instancer);
            stances.setInstance(instances.getInstance());
            ScannerDAO.em.persist(stances);

            alertitem.setPluginid(item.getPluginid());
            alertitem.setAlert(item.getAlert());
            alertitem.setName(item.getName());
            alertitem.setRiskcode(item.getRiskcode());
            alertitem.setConfidence(item.getConfidence());
            alertitem.setRiskdesc(item.getRiskdesc());
            alertitem.setDesc(item.getDesc());
            alertitem.setInstances(item.getInstances());
            alertitem.setCount(item.getCount());
            alertitem.setSolution(item.getSolution());
            alertitem.setOtherinfo(item.getOtherinfo());
            alertitem.setReference(item.getReference());
            alertitem.setCweid(item.getCweid());
            alertitem.setWascid(item.getWascid());
            alertitem.setSourceid(item.getSourceid());  
            ScannerDAO.em.persist(alertitem);               
        }


        site.setAlerts(al);
        ScannerDAO.em.persist(al);
        ScannerDAO.em.persist(site);

        ScannerDAO.em.getTransaction().commit();


    } catch (Exception e) {
        System.out.println("Exception : " + e.getMessage());
        e.printStackTrace();
    }
    ScannerDAO.em.close();
    return Response.status(200).entity(scanResult).build();       

   }

   }       

And this is the xml :

<?xml version="1.0"?>
<OWASPZAPReport generated="Sun, 25 Jun 2017 17:29:12" version="2.6.0">
<site host="127.0.0.1" name="http://127.0.0.1:8761" port="8761" 
ssl="false">
<alerts>
  <alertitem>
    <pluginid>2</pluginid>
    <alert>Private IP Disclosure</alert>
    <name>Private IP Disclosure</name>
    <riskcode>1</riskcode>
    <confidence>2</confidence>
    <riskdesc>Low (Medium)</riskdesc>
    <desc>&lt;p&gt;A private IP (such as 10.x.x.x, 172.x.x.x, 192.168.x.x) 
    or an Amazon EC2 private hostname (for example, ip-10-0-56-78) has been 
    found in the HTTP response body. This information might be helpful for 
    further attacks targeting internal systems.&lt;/p&gt;</desc>
    <instances>
      <instance>
        <uri>http://127.0.0.1:8761/</uri>
        <method>GET</method>
        <evidence>10.0.75.1</evidence>
      </instance>
      <instance>
        <uri>http://127.0.0.1:8761</uri>
        <method>GET</method>
        <evidence>10.0.75.1</evidence>
      </instance>
    </instances>
    <count>2</count>
    <solution>&lt;p&gt;Remove the private IP address from the HTTP response 
    body.  For comments, use JSP/ASP/PHP comment instead of HTML/JavaScript 
    comment which can be seen by client browsers.&lt;/p&gt;</solution>
    <otherinfo>&lt;p&gt;10.0.75.1&lt;/p&gt;&lt;p&gt;&lt;/p&gt;</otherinfo>
    <reference>&lt;p&gt;https://tools.ietf.org/html/rfc1918&lt;/p&gt;
     </reference>
    <cweid>200</cweid>
    <wascid>13</wascid>
    <sourceid>3</sourceid>
  </alertitem>
 </alerts>
</site>

and the error stackstrace :

Jul 01, 2017 1:22:16 PM org.apache.catalina.core.StandardWrapperValve 
invoke SEVERE: Servlet.service() for servlet [Jersey Web Application] in context with path [/EventService02] threw exception
 javax.persistence.RollbackException: java.lang.IllegalStateException: 
During synchronization a new object was found through a relationship that 
was not marked cascade PERSIST: Instances [id=0, instance=[Instance [id=0, 
uri=http://localhost:8761/, method=GET, evidence=null, param=X-XSS-
 Protection, attack=null, instances=null], Instance [id=0, 
   uri=http://localhost:8761/lastn, method=GET, evidence=null, param=X-XSS-
  Protection, attack=null, instances=null]]]. at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(En tityTransactionImpl.java:159)
SyCode
  • 1,077
  • 4
  • 22
  • 33
  • Choice of class names makes it very difficult to follow the code, but no where in your code do you call persist or merge on the "Instances" instance that you are setting on the other entities you call persist on - the item.getInstances() is a very different instance then the 'stances' you create. – Chris Jul 10 '17 at 15:09
  • @Chris. thanks for comment. Sorry for the naming, I actually created the classes and methods using an online tool, supplying the xml, I guess it followed the names in the original xml. I called the persist in the , check for ` ScannerDAO.em.persist(alertitem) `. – SyCode Jul 13 '17 at 07:55
  • You need to look at your object model in more detail to solve this, but calling persist on alertItem does not automatically cascade the persist unless you've set it on the relationship - which you haven't shown. So that is one spot it could be referencing an unmanaged object. Another is that your 'instance' instances have a bidirectional relationship with 'instances'. You add the 'instance' to the new 'instances' object, but leave the 'instance'.instances reference as is. This should be set to the new 'instances' object and could be referencing something else. – Chris Jul 13 '17 at 17:49

0 Answers0