Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(api-v2): Improve error message when an XSLT transformation file is not found (DSP-1404) #1831

Merged
merged 6 commits into from Mar 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -23,6 +23,7 @@ import java.util.UUID

import akka.pattern._
import org.knora.webapi._
import org.knora.webapi.exceptions.{NotFoundException, SipiException}
import org.knora.webapi.feature.FeatureFactoryConfig
import org.knora.webapi.messages.IriConversions._
import org.knora.webapi.messages.StringFormatter
Expand Down Expand Up @@ -72,7 +73,7 @@ class StandoffResponderV1(responderData: ResponderData) extends Responder(respon
featureFactoryConfig: FeatureFactoryConfig,
userProfile: UserADM): Future[GetXSLTransformationResponseV1] = {

for {
val xslTransformationFuture = for {
xsltTransformation <- (responderManager ? GetXSLTransformationRequestV2(
xsltTextRepresentationIri = xslTransformationIri,
featureFactoryConfig = featureFactoryConfig,
Expand All @@ -82,6 +83,13 @@ class StandoffResponderV1(responderData: ResponderData) extends Responder(respon
GetXSLTransformationResponseV1(
xslt = xsltTransformation.xslt
)

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(s"XSL transformation $xslTransformationIri not found: ${notFound.message}")

case other => throw other
}
}

/**
Expand Down
Expand Up @@ -1770,11 +1770,18 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt
requestingUser = requestingUser
)

for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? teiHeaderXsltRequest)
.mapTo[GetXSLTransformationResponseV2]
} yield Some(xslTransformation.xslt)

xslTransformationFuture.recover {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wieder was gelernt! This recover combinator is super cool :-)

case notFound: NotFoundException =>
throw SipiException(s"TEI header XSL transformation <$headerIri> not found: ${notFound.message}")

case other => throw other
}

case None => Future(None)
}

Expand Down Expand Up @@ -1819,11 +1826,18 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt
requestingUser = requestingUser
)

for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? teiBodyXsltRequest)
.mapTo[GetXSLTransformationResponseV2]
} yield xslTransformation.xslt

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(
s"Default XSL transformation <${teiMapping.mapping.defaultXSLTransformation.get}> not found for mapping <${teiMapping.mappingIri}>: ${notFound.message}")

case other => throw other
}
case None => throw BadRequestException(s"Default XSL Transformation expected for mapping $otherMapping")
}
}
Expand Down
Expand Up @@ -19,8 +19,10 @@

package org.knora.webapi.responders.v2

import akka.http.scaladsl.util.FastFuture
import akka.pattern._
import org.knora.webapi.IRI
import org.knora.webapi.exceptions.{NotFoundException, SipiException}
import org.knora.webapi.feature.FeatureFactoryConfig
import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.util.ConstructResponseUtilV2.{MappingAndXSLTransformation, ResourceWithValueRdfData}
Expand Down Expand Up @@ -79,15 +81,23 @@ abstract class ResponderWithStandoffV2(responderData: ResponderData) extends Res
for {
// if given, get the default XSL transformation
xsltOption: Option[String] <- if (mapping.mapping.defaultXSLTransformation.nonEmpty) {
for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? GetXSLTransformationRequestV2(
mapping.mapping.defaultXSLTransformation.get,
featureFactoryConfig = featureFactoryConfig,
requestingUser = requestingUser
)).mapTo[GetXSLTransformationResponseV2]
} yield Some(xslTransformation.xslt)

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(
s"Default XSL transformation <${mapping.mapping.defaultXSLTransformation.get}> not found for mapping <${mapping.mappingIri}>: ${notFound.message}")

case other => throw other
}
} else {
Future(None)
FastFuture.successful(None)
}
} yield
mapping.mappingIri -> MappingAndXSLTransformation(mapping = mapping.mapping,
Expand Down
Expand Up @@ -31,7 +31,7 @@ import org.apache.http.impl.client.{CloseableHttpClient, HttpClients}
import org.apache.http.message.BasicNameValuePair
import org.apache.http.util.EntityUtils
import org.apache.http.{Consts, HttpHost, HttpRequest, NameValuePair}
import org.knora.webapi.exceptions.{BadRequestException, SipiException}
import org.knora.webapi.exceptions.{BadRequestException, NotFoundException, SipiException}
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.store.sipimessages._
import org.knora.webapi.messages.v2.responder.SuccessResponseV2
Expand Down Expand Up @@ -221,14 +221,24 @@ class SipiConnector extends Actor with ActorLogging {
} yield SipiGetTextFileResponse(responseStr)

sipiResponseTry.recover {
case notFoundException: NotFoundException =>
throw NotFoundException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${notFoundException.message}")

case badRequestException: BadRequestException =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${badRequestException.message}")

case sipiException: SipiException =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${sipiException.message}",
sipiException.cause
)

case other =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${other.getMessage}"
)
}
}

Expand All @@ -254,45 +264,45 @@ class SipiConnector extends Actor with ActorLogging {
*/
private def doSipiRequest(request: HttpRequest): Try[String] = {
val httpContext: HttpClientContext = HttpClientContext.create
var maybeResponse: Option[CloseableHttpResponse] = None

val sipiResponseTry = Try {
var maybeResponse: Option[CloseableHttpResponse] = None

try {
maybeResponse = Some(httpClient.execute(targetHost, request, httpContext))
maybeResponse = Some(httpClient.execute(targetHost, request, httpContext))

val responseEntityStr: String = Option(maybeResponse.get.getEntity) match {
case Some(responseEntity) => EntityUtils.toString(responseEntity)
case None => ""
}

val statusCode: Int = maybeResponse.get.getStatusLine.getStatusCode
val statusCategory: Int = statusCode / 100
val responseEntityStr: String = Option(maybeResponse.get.getEntity) match {
case Some(responseEntity) => EntityUtils.toString(responseEntity)
case None => ""
}

// Was the request successful?
if (statusCategory == 2) {
// Yes.
responseEntityStr
val statusCode: Int = maybeResponse.get.getStatusLine.getStatusCode
val statusCategory: Int = statusCode / 100

// Was the request successful?
if (statusCategory == 2) {
// Yes.
responseEntityStr
} else {
// No. Throw an appropriate exception.
val sipiErrorMsg = SipiUtil.getSipiErrorMessage(responseEntityStr)

if (statusCode == 404) {
throw NotFoundException(sipiErrorMsg)
} else if (statusCategory == 4) {
throw BadRequestException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
} else {
// No. Throw an appropriate exception.
val sipiErrorMsg = SipiUtil.getSipiErrorMessage(responseEntityStr)

if (statusCategory == 4) {
throw BadRequestException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
} else {
throw SipiException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
}
}
} finally {
maybeResponse match {
case Some(response) => response.close()
case None => ()
throw SipiException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
}
}
}

maybeResponse match {
case Some(response) => response.close()
case None => ()
}

sipiResponseTry.recover {
case badRequestException: BadRequestException => throw badRequestException
case notFoundException: NotFoundException => throw notFoundException
case sipiException: SipiException => throw sipiException
case e: Exception => throw SipiException("Failed to connect to Sipi", e, log)
}
Expand Down
Expand Up @@ -729,7 +729,7 @@ class KnoraSipiIntegrationV1ITSpec
Await.result(response.entity.toStrict(2.seconds).map(_.data.decodeString("UTF-8")), 2.seconds)
assert(responseBodyStr.contains("Unable to get file"))
assert(responseBodyStr.contains("as requested by org.knora.webapi.responders.v2.StandoffResponderV2"))
assert(responseBodyStr.contains("Sipi responded with HTTP status code 404"))
assert(responseBodyStr.contains("Not Found"))
}

"create a resource with a PDF file attached" in {
Expand Down