icatproject / icat.server

The ICAT server offering both SOAP and "RESTlike" interfaces to a metadata catalog.
Other
1 stars 5 forks source link

NullPointerException creating a DataCollection #262

Open RKrahl opened 2 years ago

RKrahl commented 2 years ago

Creating an empty DataCollection having no content and no attributes set causes a NullPointerException in icat.server:

>>> client.apiversion
StrictVersion ('4.11.1')
>>> client.new("dataCollection").create()
ERROR:suds.client:<suds.sax.document.Document object at 0x7ffba6d0d400>
Traceback (most recent call last):
  ...
icat.exception.ICATInternalError: INTERNAL org.icatproject.core.IcatException

The relevant bits of the icat.log:

2021-12-21 16:24:51,667 ERROR [http-thread-pool::http-listener-2(3)] ICAT - Unexpected failure in Java 11.0.13
javax.ejb.EJBException: null
        at com.sun.ejb.containers.EJBContainerTransactionManager.processSystemException(EJBContainerTransactionManager.java:723) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionNoTx(EJBContainerTransactionManager.java:589) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionBeanMgTx(EJBContainerTransactionManager.java:549) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:450) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4592) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2125) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2095) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220) ~[ejb-container.jar:na]
        at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:90) ~[ejb-container.jar:na]
        at com.sun.proxy.$Proxy333.create(Unknown Source) ~[na:na]
        at org.icatproject.core.manager.__EJB31_Generated__EntityBeanManager__Intf____Bean__.create(Unknown Source) ~[EntityBeanManager.class:na]
        at org.icatproject.exposed.ICAT.create(ICAT.java:130) ~[ICAT.class:na]
        at jdk.internal.reflect.GeneratedMethodAccessor422.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
        [...]
Caused by: java.lang.NullPointerException: null
        at org.icatproject.core.manager.EntityBeanManager.create(EntityBeanManager.java:231) ~[EntityBeanManager.class:na]
        at jdk.internal.reflect.GeneratedMethodAccessor423.invoke(Unknown Source) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        [...]
RKrahl commented 2 years ago

Update: apparently, this is triggered by a bug in suds-jurko. You may skip to the conclusion below. :smile:

Analysis

suds-jurko

Debugging the situation sketched above:

>>> dc = client.new("dataCollection")
>>> dc.create()
Traceback (most recent call last):
  ...
icat.exception.ICATInternalError: INTERNAL org.icatproject.core.IcatException

Looking at the SOAP message that the client sends to the server:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://icatproject.org" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
  <ns1:Body>
    <ns0:create>
      <sessionId>b514b463-e45b-4317-bcf7-1502d7a702dc</sessionId>
    </ns0:create>
  </ns1:Body>
</SOAP-ENV:Envelope>

This is clearly broken.

Trying a variant, it works:

>>> dc = client.new("dataCollection", id=0)
>>> dc.create()
>>> dc.id
28

The SOAP message now looks like:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://icatproject.org" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
  <ns1:Body>
    <ns0:create>
      <sessionId>b514b463-e45b-4317-bcf7-1502d7a702dc</sessionId>
      <bean xsi:type="ns0:dataCollection">
    <id>0</id>
      </bean>
    </ns0:create>
  </ns1:Body>
</SOAP-ENV:Envelope>

suds-community

Trying the first version using suds-community works:

>>> dc = client.new("dataCollection")
>>> dc.create()
>>> dc.id
27

The SOAP message that suds-community sends to the server looks like:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns0="http://icatproject.org" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/">
  <SOAP-ENV:Header/>
  <ns1:Body>
    <ns0:create>
      <sessionId>69a36d8a-41ec-4beb-85b2-377ed8badf96</sessionId>
      <bean xsi:type="ns0:dataCollection"/>
    </ns0:create>
  </ns1:Body>
</SOAP-ENV:Envelope>

Conclusion

The issue is triggered by a bug in suds-jurko. Both suds versions leave out unset attributes when sending the SOAP message to the server, which is correct. But suds-jurko leaves out the entire bean element when no attribute is set at all, which is completely broken.

Nevertheless, I still maintain that this is also a bug in icat.server: it should reply either with a ParameterError or a ValidationError instead of an InternalError. A NullPointerException should not happen, regardless how defective the client input is.