3
errorString="AxisFault\n
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException\n
 faultSubcode: \n
 faultString: My Error\n
 faultActor: \n
 faultNode: \n
 faultDetail: \n
    {}string: this is the fault detail"


Pattern pattern = Pattern.compile(".*faultString(.*)", Pattern.DOTALL);
Matcher matcher = pattern.matcher(errorString);
if (matcher.matches()) {
   String match = matcher.group(1);
   return match;
}

I want to get "My Error", but it returns to the end of the whole string instead of matching to the \n at the end of the faultString line. I've tried many techniques to get it to stop at the end of the line, without success.

thanks

7 Answers 7

8

You shouldn't be passing Pattern.DOTALL; that causes newlines to be matched by .*, which is exactly what you don't want here.

A better regex would be:

Pattern pattern = Pattern.compile("faultString: (.*)");

and then, instead of matcher.matches(), use find() to see if it appears anywhere in the string.

Note also that I've modified the regex to only group the "My Error" part, instead of ": My Error" like your original one would have.

Just to be clear, here is the code I tested:

Pattern pattern = Pattern.compile("faultString: (.*)");
Matcher matcher = pattern.matcher(errorString);
if (matcher.find()) {
    System.out.println(matcher.group(1));
}

where errorString is the same as yours.
The output is:

My Error
Sign up to request clarification or add additional context in comments.

4 Comments

this is what i'm looking for. still curious how to make it work with matches though.
With matches(), you would use ".*faultString: ([^\\n]*).*" with Pattern.DOTALL, as described by Chris Thornhill and Mike Digdon.
But I prefer not to use extraneous dots if I can help it (see Jan Goyvaerts's article regular-expressions.info/dot.html ). In this case it won't make a difference, but for future reference, just try to match what you need. (Also, I would prefer to pull the Pattern object out into a static final variable to avoid recompiling it on every invocation.)
It's important to realize the difference between Matcher.matches() and Matcher.find(). The matches method attempts to match the entire input sequence against the pattern. It won't return true unless the pattern matches the entire string from start to end. This is often used with ^ and $ to denote the beginning and end of the string. The find method scans the input sequence looking for the next subsequence that matches the pattern. It will return true if the pattern occurs anywhere in the string.
2

I'd probably clean up Chris's regex to the following: ".*faultString:\\s*([^\\n]*).*"

Comments

1
Pattern pattern = Pattern.compile("^faultString(.*)$", Pattern.MULTILINE);

2 Comments

^faultString will cause trouble; it looks like there's a leading space. How about "\\bfaultString: .*$" instead? +1 for Pattern.MULTILINE regardless; that's the key point.
Actually, the key point is using find() instead of matches().
1

This looks like property file format. Would it be easier to load this string into a java.util.Property using StringReader and then reading from it?

1 Comment

i'm trying to force myself to solve string parsing issues by using regex for a while so I can actually learn regular expressions better. i rarely use them, but would like to get better at it. i could solve this problem much faster by other approaches of course, but I want to expand my skillset..
1

This works with the .matches() approach:

Pattern pattern = Pattern.compile(".*faultString([^\\n]*).*", Pattern.DOTALL);

Comments

1

Keep in mind that regex stuff is expensive. Chetan has the right idea.

Here's some sample code--

    String errorString = "AxisFault\n"
            + "          faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.generalException\n"
            + "          faultSubcode: \n" 
            + "          faultString: My Error\n"
            + "          faultActor: \n" 
            + "          faultNode: \n"
            + "          faultDetail: \n"
            + "                 {}string: this is the fault detail";

    Properties p = new Properties();
    ByteArrayInputStream bis = new ByteArrayInputStream(errorString
            .getBytes());

    try {
        p.load(bis);
    } catch (IOException e) {

    }

    System.out.println(p.toString());
    System.out.println(p.getProperty("faultString"));

1 Comment

I don't think Properties handles delimiters other than '='. Certainly a custom parser could be faster, but one doesn't generally need to worry too much about the performance of error reporting.
0

Maybe getFaultString? :)

edit: or ((AxisFault) exception.getRootCause()).getFaultString(). I just thought that you maybe overlooked the fact that you can get that directly from AxisFault itself.

2 Comments

i want to pull several fields.
actually after looking more closely at AxisFault your approach makes more sense. regex is way over-engineering. still a good exercise to mess with the reg ex stuff tho.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.