twitter / finatra

Fast, testable, Scala services built on TwitterServer and Finagle
https://twitter.github.io/finatra/
Apache License 2.0
2.27k stars 405 forks source link

Ability to pass in already instantiated objects to custom ExceptionMapper classes #541

Closed alilewin92 closed 4 years ago

alilewin92 commented 4 years ago

I'm wondering if there's a way to pass in your own arguments to the HttpRouter custom ExceptionMappers since currently it seems like it only takes in the class rather than an already initialized class instance.

Expected behavior

The expected behavior would be the ability to pass in an already instantiated class, for example I would want to create a custom ExceptionMapper that could have extra args:

// example custom exception mapper which takes in additional args:
class FakeExceptionMapper @Inject()(response: ResponseBuilder, customArg: SomeCustomObject1) extends ExceptionMapper[Throwable] {
    ...
}

Then the code in the http server could look something like:

val arg1: SomeCustomObject1 = SomeCustomObject1(...)
val myCustomMapper: MyCustomExceptionMapper = new MyCustomExceptionMapper(arg1)
router.exceptionMapper[myCustomMapper]

Or, we can also have a way to pass in just the class type and any additional arguments:

router.exceptionMapper[MyCustomExceptionMapper, arg1, arg2...]

Actual behavior

Right now we are only able to pass in the Class, not an actual instance and no potential parameters:

router.exceptionMapper[MyCustomExceptionMapper]

Steps to reproduce the behavior

No steps to reproduce since this isn't actually a bug (and sorry if this isn't the right spot for this post). I'm just hoping to understand if this is achievable or if there's a recommended workaround. Thanks!

cacoco commented 4 years ago

Hi @alilewin92

Calling router.exceptionMapper[MyCustomExceptionMapper] is adding the mapper by type which is a signal for the instance to be constructed from the injector. Meaning that if you have the constructor marked with @Inject() then the constructor args will be provided by the injector if possible. If the injector cannot provide the arguments, then it will look for a module which can an instance of the mapper. If it can't find a way to provide an instance for the type, then the code will fail.

Or you can simply add an instance yourself by doing, router.exceptionMapper(new MyCustomExceptionMapper(arg1)).

There's more information here: https://twitter.github.io/finatra/user-guide/http/exceptions.html#how

But you may also want to take a look at the documentation around the use of injection in the framework: https://twitter.github.io/finatra/user-guide/getting-started/basics.html

Hope that helps.

Closing as I think this answers the question. Thanks!