Use Eclipse Conditional Breakpoint to Execute Arbitrary Code to Fix Real Problem


When debug the problem: Solr post failed with error Illegal character ((CTRL-CHAR, code 22))  - about the problem and solution, please see
Solr: XML Contains Invalid Control Characters

I have to find what XML data contains invalid characters, there are several ways, here I would like to introduce how to use Eclipse Conditional Breakpoint.

First, look at the stack trace:
SEVERE: [com.ctc.wstx.exc.WstxLazyException] com.ctc.wstx.exc.WstxUnexpectedCharException: Illegal character ((CTRL-CHAR, code 22))
 at [row,col {unknown-source}]: [1,128]
at com.ctc.wstx.exc.WstxLazyException.throwLazily(WstxLazyException.java:45)
at com.ctc.wstx.sr.BasicStreamReader.safeFinishToken(BasicStreamReader.java:3659)
org.apache.solr.handler.loader.XMLLoader.readDoc(XMLLoader.java:393)
First I enabled remote debug, then put a break point at below location, so Solr will pause when hit the exception.
protected void com.ctc.wstx.sr.BasicStreamReader.safeFinishToken()
{

 try {
  boolean deferErrors = (mCurrToken == CHARACTERS);
  finishToken(deferErrors);
 }
 catch (IOException ioe) 
 {
  throwLazyError(ioe); // Breakpoint here
 }
 catch (XMLStreamException strex)
 {
  throwLazyError(strex);
 }

}
Next I need figure outthe content of xml body, so I can show to tester and developers of other component. Because this is a post request, we can't see the content directly from streams of SolrQueryRequest instance.

We can't view content of HttpRequestContentStream , but we can view content of StringStream.
And I have an util that can clone SolrQueryRequest instance to a StringStream-based SolrQueryRequest. Please read how to Clone SolrQueryRequest 

Next where and how I can execute the code to clone clone SolrQueryRequest instance to a StringStream-based SolrQueryRequest?

Eclipse Conditional Breakpoint comes to rescue in this case.

In an Eclipse Conditional Breakpoint, we can execute arbitrary code as long as it return a boolean value at alst.

So I add a Conditional Breakpoint in the first line of method: org.apache.solr.handler.RequestHandlerBase.handleRequest(SolrQueryRequest req, SolrQueryResponse rsp)

The condition looks like below:
req = org.jefferyyuan.SolrUtil.cloneSolrRequest(req);
return false;
Eclipse will excute the statements in declaration of Conditional Breakpoint which will replace the original SolrQueryRequest instance to a StringStream-based SolrQueryRequest object.
"return false" tells Eclipse not to break.

So now when the application hits the exception, I can go to the stack at org.apache.solr.handler.RequestHandlerBase.handleRequest, and view and copy the xml data.

We have to use full qualified classname(org.jefferyyuan.SolrUtil) in Conditional Breakpoint statements, as in current context, the JVM doesn't know SolrUtil.

If we have not defined a util method like above yet, we can copy the following statements to the conditional breakpoint.
org.apache.solr.request.SolrQueryRequestBase newReq = new org.apache.solr.request.LocalSolrQueryRequest(req.getCore(),
 req.getParams());
Iterable<org.apache.solr.common.util.ContentStream> iterable = req.getContentStreams();
if (iterable != null) {
  Iterator<org.apache.solr.common.util.ContentStream> it = iterable.iterator();
  List<org.apache.solr.common.util.ContentStream> newStreams = 
 new ArrayList<org.apache.solr.common.util.ContentStream>();
  while (it.hasNext()) {
 org.apache.solr.common.util.ContentStream oldStream = it.next();
 if (oldStream instanceof org.apache.solr.common.util.ContentStreamBase.StringStream) {
   newStreams.add(oldStream);
 } else {
   java.io.InputStream is = oldStream.getStream();
   String streamContent = org.apache.commons.io.IOUtils.toString(is);
   org.apache.solr.common.util.ContentStreamBase.StringStream sStr = 
  new org.apache.solr.common.util.ContentStreamBase.StringStream(streamContent);
   sStr.setContentType(oldStream.getContentType());
   sStr.setName(oldStream.getName());
   sStr.setSize(oldStream.getSize());
   sStr.setSourceInfo(oldStream.getSourceInfo());
   newStreams.add(sStr);
 }
  }
  newReq.setContentStreams(newStreams);
}
req = newReq;
return false;

Resource
Solr: Clone Solr Request
Solr: XML Contains Invalid Control Characters

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)