If there are NPEs resulting from invalid records, and you have no control over the records, then your logic should attempt to validate the records before processing them. The best way to do this would be to loop over each record, checking for the valid format, keeping track of invalid rows. After validation, if any invalid rows exist, you can report them in a meaningful format back to the UI. Otherwise proceed with the actual processing.
List<String> invalidRows = new ArrayList<String>();
for each row {
if (row is missing x) {
invalidRows.add("Record " + rowNumber + " is missing X");
}
if (row is missing y) {
invalidRows.add("Record " + rowNumber + " is missing Y");
}
}
if (invalidRows.isEmpty()) {
//process
}
else {
format and return error message using data collected
}
(note that the use of a List<String> is a general example - you should store and then format this information in the way that makes the most sense for your situation.)
An alternative to this approach would be to do your validation and processing in the same loop, keeping track of invalid rows and processing valid ones. At the end, the UI could report how many succeeded and which failed.
Additionally, one might wrap web services in a last defense to make unhandled exceptions more manageable and consumable by the client UI, or at least easier for you to read:
@WebMethod(operationName = "myMethod")
public String myMethod() {
try {
//logic
return "done";
}
catch (Throwable error) {
//returns formatted String representing error - UI should check for this
return MyExceptionFormatter.formatUnhandled(error);
}
}
Your custom formatting would assemble a more meaningful String representing the exception, potentially in XML format. This all depends on what your client UI is expecting.