Ask a Question

getXmlHolder is generating a nullPointerException

AngieD18
Occasional Contributor

getXmlHolder is generating a nullPointerException

Hi Smartbears,

 

The following code is not working in Ready API v3.9.1.  The issue is with the groovyUtils.getXmlHolder statement, it is throwing an error.  

 

      def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
      def holder = context.expand( '${SOAPRequest#Response}' )
      def requestHolder = groovyUtils.getXmlHolder( holder )

 

The context.expand is retrieving the request's response (first few lines below):

       holder= <soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
             <soap:Header>
             <wsse:Security soap:mustUnderstand="true" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
             <ds:Signature Id="SIG-8e536e7f-6d9c-406b-b84e-6f90e5d1db1f" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
             <ds:SignedInfo>


Error displayed:

        java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null See Error Log for details.

 

From the Error Log:

      Wed Jan 26 12:00:31 EST 2022: ERROR: An error occurred in the script of the Groovy Script test step [Groovy Script - Value Retrieval]:
      Wed Jan 26 12:00:31 EST 2022: ERROR: java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null
      java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null

 

This is a silly question, but could this error be related to my response having an WS-Security error?  If it is related to the WS-Security error, is there anyway to get around this?  I am working in our test environment.

 

WS-Security error:

  • org.apache.ws.security.WSSecurityException: The signature or decryption was invalid

 

Thank you,

Angie

6 REPLIES 6
richie
Community Hero

Hey @AngieD18,

Have you progressed with this at all yet?

Im not best placed to answer this one as im not a groovy whizz (perhaps @nmrao or @ChrisAdams can help), but as no one else has responded i'll answer as best i can.

I dont really see how your ws security issue would cause a problem with xmlHolder. I had a look at the xmlHolder class details and the entrySet() method does relate to xmlHolder.

Theres no obvious issues with your groovy syntax as far as i can tell. At work im waiting to be given access to repo that holds all our SOAP ReadyAPI projects, hopefully this is on Monday or Tuesday at latest.
I know the SOAP projects use the embedded functionality, but i'll plug the groovy together and try and replicate. Im using v3.20.0 so it wont be a like for like replication attempt, but it's the best i got right now.

Cheers,

Rich
if this helped answer the post, could you please mark it as 'solved'? Also if you consider whether the title of your post is relevant? Perhaps if the post is solved, it might make sense to update the Subject header field of the post to something more descriptive? This will help people when searching for problems. Ta

Hi,

The stack trace mentions the WS-security error and you have the xml issue to.

My first suggestion would be to disable the Groovy script step and check the service call.

Once the service call is properly working, then move onto the assertion.

 

AngieD18
Occasional Contributor

Hi.

Sorry, my laptop was in the shop.  Just it back today.  🙂

 

You are so right.  This has nothing to do with security exception.  I reworked that code to use XmlSlurper.  But now, writing another Groovy script, I am getting the same error.  The issue is with the getXmlHolder statement.  The problem is with the Map being returned empty (null).  I have never encountered this before.  The request exists and is not large, only 140 lines.  No special characters beyond $ and @.  What should I be looking for?  Any ideas how I can resolve this?

 

def holder = groovyUtils.getXmlHolder( request )

 

The request does exist:

  • INFO: request= 576040 PSRSTAR No Angie D xxxxx 01-2176 PRRB 16-0047 12/31/2017 xxxx No 51 DSH - Code 2 & 3 Eligible Days 11/24/2021 N NPR 06/01/2021 N/A 1, 2, 4, 6, 7, 9, 20, 21, 22 176 $16,341 No No xxxxxx No 44 DSH - Dual Eligible Days - Exhausted 11/24/2021 N NPR 06/01/2021 N/A 1, 2, 4, 6, 7, 9, 20, 21, 22 176 $25,192 No No xxxxxx No 124 DSH - Dual Eligible Part C Days 11/24/2021 N NPR 06/01/2021 N/A 1, 2, 4, 6, 7, 9, 20, 21, 22 176 $12,936 No No xxxxxx No 143 DSH - SSI Systemic Errors 11/24/2021 N NPR 06/01/2021 N/A 1, 2, 4, 6, 7, 9, 20, 21, 22 176 $98,043 No No 100000035 Team2 11/24/2021 11/24/2021 11/29/2021 11/29/2021 1 Scheduled 01/15/2022 No 07/22/2022 09/20/2022 11/19/2022 Dignity Health Kenton Fong  10901 GOLD CENTER DRIVE, SUITE 300RANCHO CORDOVACACALIFORNIA956709166313612brent.smith@seniorhealth.org

Displayed error:

java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null See Error Log for details.

 

From the Error.log:

Wed Feb 02 23:51:11 EST 2022: ERROR: An error occurred in the script of the Groovy Script test step [Groovy Script - Value Set]:
Wed Feb 02 23:51:11 EST 2022: ERROR: java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null
java.lang.NullPointerException: Cannot invoke "java.util.Set.iterator()" because the return value of "java.util.Map.entrySet()" is null
at org.codehaus.groovy.runtime.InvokerHelper.formatMap(InvokerHelper.java:715)
at org.codehaus.groovy.runtime.InvokerHelper.format(InvokerHelper.java:655)
at org.codehaus.groovy.runtime.InvokerHelper.toString(InvokerHelper.java:152)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.toString(DefaultGroovyMethods.java:15381)
at org.codehaus.groovy.runtime.StringGroovyMethods.plus(StringGroovyMethods.java:2121)
at org.codehaus.groovy.runtime.dgm$1211.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:247)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:139)
at com.eviware.soapui.support.xml.Script102.overrideNode(Script102.groovy:179)
at com.eviware.soapui.support.xml.Script102$overrideNode$0.callCurrent(Unknown Source)
at com.eviware.soapui.support.xml.Script102.run(Script102.groovy:424)

 

Take care,

Angie

Hi Angie,

There's a few bits here....

I'm assuming you've fixed your original assertion.  The one thing I was going to suggest was the value to pass into the XML Sluper.

 

You wrote....

 

      def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
      def holder = context.expand( '${SOAPRequest#Response}' )
      def requestHolder = groovyUtils.getXmlHolder( holder )

 

 

Whereas, I'd usually use....

 

      def groovyUtils = new com.eviware.soapui.support.GroovyUtils( context )
      def holder = context.expand( '${SOAPRequest#ResponseAsXml}' )  // This line has the change.
      def requestHolder = groovyUtils.getXmlHolder( holder )

 

 

I thought this was the issue, then I re-read your latest response.  The request does not look like XML.  If it isn't XML then the slurper cannot work with it.

If this was me, the first thing I'd do is log the request and the raw request.  E.g.

 

    def request = context.expand( '${SOAPRequest#Request}' ) ;
    log.info(request);

    def rawRequest = context.expand( '${SOAPRequest#RawRequest}' ) ;
    log.info(rawRequest);

 

 

I appreciate that this is not the solution, but it may get us a step or two towards that.

 

 

AngieD18
Occasional Contributor

Hi.

I was using XmlSlurper, but I could not figure out how to update the request with my new values.  I have an Excel spreadsheet that includes the name of the nodes (EX: issueTypeId) whose values I need to capture.  I am able to pull the needed nodes from the response and save them as TestCase properties.  The next step is to update a request with those values.  I do not know the nodes in advance or how many, so I cannot use the regular soapUI property transfer method.  I have XmlSlurper code that finds the nodes in the request, but then I am stuck.

 

def holder = context.expand( '${SOAPRequest#Request}' )
def slurper=new XmlSlurper( false, false, false )
def resq = slurper.parseText( holder )

 

def dataCnt=0
resq.'**'.findAll { it.name() == nodeToUpdate } {
      it.text()=propToUse[dataCnt]

      dataCnt++

}

 

I know this all sounds crazy.  Any ideas?

Thank you,

Angie

Hi,

 

I think I know where you're going.  Dynamic request based on response from earlier request.  Not crazy or science fiction.

 

Is your second request payload XML or JSON?  My idea would be the same for either, but you'd have to translate.

 

I'm going to have to make some assumptions, but I'll give an idea a go.  By the way, you don't need property transfers.

Say your second (the dynamic) request is XML and the payload might be....

<ns1:someCustomerServiceRequest>
     <ns1:customerId>1001</ns1:customerId>
</ns1:someCustomerServiceRequest>

 

Or....

<ns1:someCustomerServiceRequest>
     <ns1:customerSurname>Lennon</ns1:customerSurname>
</ns1:someCustomerServiceRequest>

 

And it's the id or surname that is the changing bit in your test, you could change it to....

<ns1:someCustomerServiceRequest>
     ${Get Customer Service Payload - Groovy Script#result}
</ns1:someCustomerServiceRequest>

 

This Groovy script called "Get Customer Service Payload - Groovy Script" must be in between service calls one and two.

 

In the Groovy script, implement the loop you built earlier, but for each value you want to pass to the second service, create the node of interest.  E.g.

def nodeOfInterest = ${DataSource#NODEOFINTEREST}

def valueOfInterest = "however you pull the value from the response of the first request."

def node = "<ns1:${nodeOfInterest}>${valueOfInterest}</ns1:$nodeOfInterest>";
log.info(node)  // Let's have a quick look at what we've built.

return node;  //This returns that value and will stick it in the second payload.

 

 

cancel
Showing results for 
Search instead for 
Did you mean: