null pointer exception

I am taking the input as string , substring that string to 256 charectors and add it to document list. at last i want to add whole string to document list.
But i am getting null pointer exception
Please find the code below:


// pipeline
IDataCursor pipelineCursor = pipeline.getCursor();
// stringtotal
IData stringtotal = IDataUtil.getIData( pipelineCursor, “stringtotal” );
if ( stringtotal != null)
{
IDataCursor stringtotalCursor = stringtotal.getCursor();
String stringaa = IDataUtil.getString( stringtotalCursor, “stringaa” );
if(stringaa !=null)
{
int lengthofstr = stringaa.length();
int count = lengthofstr/256;
for(int i=0;i<count;i++)
{
int startindex = 0;
int endindex = 256;
String target = stringaa.substring(startindex, endindex);
startindex=startindex + 256;
endindex=endindex + 256;
IData[] IT_DATA = new IData[1];
if ( IT_DATA != null)
{
for ( int j = 0; j < IT_DATA.length; j++ )
{
IDataCursor IT_DATACursor = IT_DATA[j].getCursor();
IDataUtil.put( IT_DATACursor, “DATA”, target );
//String DATA = IDataUtil.getString( IT_DATACursor, target );
IT_DATACursor.destroy();
}
}
IDataUtil.put( pipelineCursor, “IT_DATA”, IT_DATA );
}
stringtotalCursor.destroy();
}
}
pipelineCursor.destroy();

It’d be helpful if you could tell us which line is actually throwing the NullPointerException, but I imagine it’s this line: IDataCursor IT_DATACursor = IT_DATA[j].getCursor();

The reason why is because you’ve created the IData array: IData[] IT_DATA = new IData[1];

But you didn’t actually instantiate the IData object inside the array. You need to do that using IDataFactory.

By the way, I’m assuming you’re still playing around with the code, right? Because there are a couple of flaws in your logic.

Here’s my suggestion: first, attempt to write this service by having a string as input (instead of Document w/ string) and having a string array as output (instead of Document List w/ string). See if you can get that to work. Then, if needed (and I don’t see why it would be needed), you can try to modify the code by adding the IData pieces.

  • Percio

My suggestion is to write this service using FLOW instead of Java. With the available built-in services, it should be doable.

How to achive this functionality by using available built-in services in webMethods.

The FLOW elements you’ll use are LOOP and BRANCH along with built-in services pub.string:substring, pub.string. length, pub.math:addInts, pub.math:divideInts, and pub.list:appendToStingList or pub.list:appendToDocumentList depending on whether you want a string list or a document list with each document holding a string.

Follow the basic logic you have in your Java service and you should be able to create the equivalent in FLOW, without having to mess with the IData and IDataCursor stuff.

:o

I can’t think of a way to do this in Flow without opening a can of worms. Doesn’t mean it can’t be done, but my two years of WM experience haven’t shown me a way. In particular without an input array, a LOOP step is no use (or have I missed something?), and REPEAT is “interesting” to say the least.

My recommendation would be to work on the algorithm outside of WebMethods. Write a Java method:

private static String[] splitString(String input, int chunkLength) {
  // implementation
}

Test it, and test it well - zero length inputs, null inputs, input.length == chunkLength, etc.

Then paste that code into the ‘Shared’ tab of your Java service. Let Developer convert your service inputs and outputs into IData parsing stuff. Make minor changes to the autogenerated code, to call your splitString method.

Oh, and use the Java collections framework to make your implementation of the method easier.

Aw sod it:

    /**
     * Splits a string into an array of Strings, each of the requested size.
     * The final string in the array may of course be shorter.
     * @param input A string to split
     * @param chunkSize Size of the desired chunks
     * @return the chunks as requested.
     */
    public static String[] splitString(String input, int chunkSize) {
        
        List strings = new ArrayList();
        while(input.length() > 0) {
            int thisLen = java.lang.Math.min(chunkSize, input.length());
            strings.add( input.substring(0, thisLen) ); // put chunk on list
            input = input.substring(thisLen); // drop chunk from input
        }
        return (String[]) strings.toArray(new String[0]);
    }

(Hoping that I’ve understood your intention). I daresay it could be made more efficient, but this way it’s nice and easy to understand.

Of course this fails with a null input. I’ll leave fixing that as an exercise for the reader.

PS it would be perfectly appropriate to then use a Flow service to LOOP over the String[] that comes out of that Java, and map it to the output structure you want. Flow’s good at that.

Oops. My bad. I did indeed mean REPEAT, not LOOP.

I’ll take a stab at doing this and post the results.

service: chunkString
inputs: str (string), size (string)
outputs: list (string list)

MAP (Map str to local var s)
BRANCH on '/s'
.. $null: SEQUENCE (No string passed in; do nothing)
.. $default: REPEAT (on success)
.... pub.string:length (length of s)
.... BRANCH on '/length'
...... 0: EXIT '$loop' (Done)
...... $default: SEQUENCE
........ pub.string.substring (Get the chunk from s)
........ pub.list.appendToStringList (Add the chunk to the list)
........ BRANCH (evaluate labels = True)
.......... %/length% < %/size%: MAP (Last chunk, so just empty s)
.......... $default: pub.string:substring (Drop "size" chars from front of s)
MAP (pipeline cleanup)

The Java service is probably the better approach in this case. But just wanted to show it can be done!

If you do use the Java service, might I suggest avoiding the name “splitString” since Java’s String class has a “split” method that does something quite different. Using split in your name might introduce confusion.