scalaeither

Scala : Expression of Type None. Type doesn't confirm to expect type Document


I am new to Scala coding. I have below code snippet which builds document using documentBuilder. My input is XML. Whenever I input an malformed XML below code is failing to parse and raising SAXException.

def parse_xml(xmlString: String)(implicit invocationTs: Date) : Either [None, Document] = {
 try {
   println(s"Parse xmlString invoked")
   val document = documentBuilder(false).parse(new InputSource(new StringReader(xmlString)))
   document.getDocumentElement.normalize()
   //Right(document)
   document
 } catch {
   case e: Exception => None

SAXException is raised because of the inbuilt implementation of parse function. Please see below code where SAXException is being handled:

public abstract Document parse(InputSource is)
    throws SAXException, IOException;

Now I am trying to bypass this SAXException as I don't want my job to failed just because of one malformed XML. So I have put try catch block handling below exception :

case e: Exception => None

But it's showing error here as "Expression of Type None. Type doesn't confirm to expect type Document" as my return type is document.

How can I get rid of this issue?


Solution

  • If you want to use wrappers, like Either or Option you always have to wrap returned value.

    In case you want to pass exception further, better choice than Either might be Try:

    def parse_xml(xmlString: String)(implicit invocationTs: Date) : Try[Document] = {
        try {
          println(s"Parse xmlString invoked")
          val document = documentBuilder(false).parse(new InputSource(new StringReader(xmlString)))
          document.getDocumentElement.normalize()
          Success(document)
        } catch {
          case e: Exception => Failure(e)
        }
    }
    

    You could even simplify it by wrapping block inside Try.apply:

    Try{
       println(s"Parse xmlString invoked")
       val document = documentBuilder(false).parse(new InputSource(new StringReader(xmlString)))
       document.getDocumentElement.normalize()
       document
    }
    

    If you don't care about exception, just about result, use Option:

    def parse_xml(xmlString: String)(implicit invocationTs: Date) : Option[Document] = {
         try {
           println(s"Parse xmlString invoked")
           val document = documentBuilder(false).parse(new InputSource(new StringReader(xmlString)))
           document.getDocumentElement.normalize()
           Some(document)
         } catch {
           case e: Exception => None
         }
    }