How to Add an API Route¶
Write SPARQL templates¶
Add any SPARQL templates you need to src/main/twirl/queries/sparql/v1, using the Twirl template engine.
Write Responder Request and Response Messages¶
Add a file to the org.knora.webapi.messages.v1respondermessages
package, containing case classes for your responder’s request and
response messages. Add a trait that the responder’s request messages
extend. Each request message type should contain a UserProfileV1.
Response message classes that represent a complete API response must
extend KnoraResponseV1, and must therefore have a toJsValue
method that converts the response message to a JSON AST using
spray-json.
Write a Responder¶
Write an Akka actor class that extends ResponderV1, and add it to
the org.knora.webapi.responders.v1 package.
Give your responder a receive() method that handles each of your
request message types by generating a Future containing a response
message, and passing the Future to ActorUtils.futureToMessage(). See
Futures with Akka and Error Handling for details.
See Triplestore Access for details of how to access the triplestore in your responder.
Add an actor pool for your responder to application.conf, under
actor.deployment.
In ResponderManagerV1, add a reference to your actor pool. Then add
a case to the receive() method in ResponderManagerV1, to
match messages that extend your request message trait, and forward them
to that pool.
Write a Route¶
Add an object to the org.knora.webapi.routing.v1 package for your
route. Your object should look something like this:
import akka.actor.ActorSystem
import akka.event.LoggingAdapter
import org.knora.webapi.SettingsImpl
import org.knora.webapi.messages.v1respondermessages.SampleGetRequestV1
import org.knora.webapi.routing.RouteUtils
import spray.routing.Directives._
import spray.routing._
import org.knora.webapi.util.StringConversions
import org.knora.webapi.BadRequestException
object SampleRouteV1 extends Authenticator {
def knoraApiPath(_system: ActorSystem, settings: SettingsImpl, log: LoggingAdapter): Route = {
implicit val system: ActorSystem = _system
implicit val executionContext = system.dispatcher
implicit val timeout = settings.defaultTimeout
val responderManager = system.actorSelection("/user/responderManager")
path("sample" / Segment) { iri =>
get { requestContext =>
val userProfile = getUserProfileV1(requestContext)
val requestMessage = makeRequestMessage(iri, userProfile)
RouteUtils.runJsonRoute(
requestMessage,
requestContext,
settings,
responderManager,
log
)
}
}
}
private def makeRequestMessage(iriStr: String, userProfile: UserProfileV1): SampleGetRequestV1 = {
val iri = StringConversions.toIri(iriStr, () => throw BadRequestException(s"Invalid IRI: $iriStr"))
SampleGetRequestV1(iri, userProfile)
}
}
Finally, add your knoraApiPath() function to the apiRoutes member variable in KnoraService. Any exception
thrown inside the route (e.g., input validation, getUserProfile, etc.) will be handled by the KnoraExceptionHandler,
so that the correct client response (status code, format) will be returned.