Is there any difference between using #hostListener and ElementRef in a directive? - angular2-directives

In my Angular 2 app I have a directive (#Directive, not #Component) which needs to access the element to which it's applied to listen to certain DOM events.
I managed to do it in the following 2 ways.
I would like to know if one is more appropriate (more efficient / reliable) and if there's any substantial difference between the 2 approaches:
ElementRef
constructor(private _element: ElementRef) {}
...
this._element.nativeElement.addEventListener('drop', (e: any) => {
...
}
#HostListener
#HostListener('change') onChange(): void {
...
}

Related

Send upstream exception in SharedFlow to collectors

I want to achieve the following flow logic in Kotlin (Android):
Collectors listen to a List<Data> across several screens of my app.
The source-of-truth is a database, that exposes data and all changes to it as a flow.
On the first initialization the data should be initialized or updated via a remote API
If any API exception occurs, the collectors must be made aware of it
In my first attempt, the flow was of the type Flow<List<Data>>, with the following logic:
val dataFlow = combine(localDataSource.dataFlow, flow {
emit(emptyList()) //do not wait for API on first combination
emit(remoteDataSource.suspendGetDataMightThrow())
}) { (local, remote) ->
remote.takeUnless { it.isEmpty() }?.let { localDataSource.updateIfChanged(it) }
local
}.shareIn(externalScope, SharingStarted.Lazily, 1)
This worked fine, except when suspendGetDataMightThrow() throws an exception. Because shareIn stops propagating the exception through the flow, and instead breaks execution of the externalScope, my collectors are not notified about the exception.
My solution was to wrap the data with a Result<>, resulting of a flow type of Flow<Result<List<Data>>>, and the code:
val dataFlow = combine(localDataSource.dataFlow, flow {
emit(Result.success(emptyList())) //do not wait for API on first combination
emit(runCatching { remoteDataSource.suspendGetDataMightThrow() })
}) { (local, remote) ->
remote.onSuccess {
data -> data.takeUnless { it.isEmpty() }?.let { localDataSource.updateIfChanged(it) }
}
if (remote.isFailure) remote else local
}.shareIn(externalScope, SharingStarted.Lazily, 1)
I can now collect it as follows, and the exception is passed to the collectors:
dataRepository.dataFlow
.map { it.getOrThrow() }
.catch {
// ...
}
.collect {
// ...
}
Is there a less verbose solution to obtain the exception, than to wrap the whole thing in a Result?
I am aware that there are other issues with the code (1 API failure is emitted forever). This is only a proof-of-concept to get the error-handling working.

Axonframework, how to use MessageDispatchInterceptor with reactive repository

I have read the set-based consistency validation blog and I want to validate through a dispatch interceptor. I follow the example, but I use reactive repository and it doesn't really work for me. I have tried both block and not block. with block it throws error, but without block it doesn't execute anything. here is my code.
class SubnetCommandInterceptor : MessageDispatchInterceptor<CommandMessage<*>> {
#Autowired
private lateinit var privateNetworkRepository: PrivateNetworkRepository
override fun handle(messages: List<CommandMessage<*>?>): BiFunction<Int, CommandMessage<*>, CommandMessage<*>> {
return BiFunction<Int, CommandMessage<*>, CommandMessage<*>> { index: Int?, command: CommandMessage<*> ->
if (CreateSubnetCommand::class.simpleName == (command.payloadType.simpleName)){
val interceptCommand = command.payload as CreateSubnetCommand
privateNetworkRepository
.findById(interceptCommand.privateNetworkId)
// ..some validation logic here ex.
// .filter { network -> network.isSubnetOverlap() }
.switchIfEmpty(Mono.error(IllegalArgumentException("Requested subnet is overlap with the previous subnet.")))
// .block() also doesn't work here it throws error
// block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-
}
command
}
}
}
Subscribing to a reactive repository inside a message dispatcher is not really recommended and might lead to weird behavior as underling ThreadLocal (used by Axox) is not adapted to be used in reactive programing
Instead, check out Axon's Reactive Extension and reactive interceptors section.
For example what you might do:
reactiveCommandGateway.registerDispatchInterceptor(
cmdMono -> cmdMono.flatMap(cmd->privateNetworkRepository
.findById(cmd.privateNetworkId))
.switchIfEmpty(
Mono.error(IllegalArgumentException("Requested subnet is overlap with the previous subnet."))
.then(cmdMono)));

Typing keys when using with t useTranslation hook

I'm trying to bring type safety to usage of the t function, from the useTranslation hook. I've seen the following thread which expands on the Resources interface but I think it's not exactly what I'm trying to do.
https://github.com/i18next/react-i18next/issues/1280
What I would like to do is the following:
// namespaces - A, B, both have key "hello"
import { useTranslation, TranslationKeys } from 'react-i18next';
export function Blah() {
const { t } = useTranslation();
return <div>{t(TranslationKeys.hello)}</div>;
}
I don't want us as developers to be aware of different namespaces, just to deal with a single merged set of keys. Any help would be really appreciated.
As per: https://react.i18next.com/latest/typescript#create-a-declaration-file
We have 3 namespaces - sport, common and stuff in order of important to least important.
For the TS typings we just merged the contents into the sport namespace which is also the default and this has done fine.
declare module 'react-i18next' {
interface Resources {
'sport': typeof sport & typeof common & typeof stuff;
}
}

kotlin kotest/kotlintest BehaviorSpec afterSpec/finalizeSpec called too often or not at all

I have a kotlin kotest (formerly known as kotlintest) BehaviorSpec
with one Given("...") and many When("...") Then("...") under it
I want to execute a cleanup after the whole Spec (respectively every Given clause) has finished.
#MicronautTest
class StructurePersistSpec(
private val iC : InstancesC
) : BehaviorSpec({
// afterSpec {
finalizeSpec {
cleanup()
}
Given("...") {
When("...") {
Then("...") {
...
}
Then("...") {
...
}
}
When("...") {
Then("...") {
...
}
Then("...") {
...
}
}
}
...
}
on using afterSpec { } I get multiple calls (amount of Whens??) to the afterSpec { } clause and NOT just one after the Spec finished (or finishing of the/each Given Clause)
on using finalizeSpec { } it does NOT get called at all (breakpoint inside it is never hit)
what am I doing wrong?
or did I miss some fancy characteristics of BehaviorSpecs ?
The reason you are getting multiple calls is that probably you have set a different IsolationMode for your test.
That would mean your Spec will be recreated (and then cleaned) for every test. In order to have a single afterSpec call from the framework, your IsolationMode must be set to SingleInstance.
Bare in mind that might affect the way your tests are being executed hence their validity or ability to pass.
Documentation: https://kotest.io/isolation_mode/

Post API using Ratpack and Groovy giving 405 Error and RxJava methods not working

I am building an API using Ratpack and Groovy. The POST API is always giving:
405-Method not Found Error
This is a snippet from POST Endpoint Handler. In this code, promiseSingle, then, observe, map, doOnNext, doOnError, etc.
RxJAVA functions are not working. Is there any reason why RxJava methods are not working?
saveJsonAsData(context, id)
.promiseSingle()
.then { Data updateddata ->
context.response.headers
.add(HttpHeaderNames.LOCATION, "/api/save/${updateddata.id}/${updateddata.value}")
context.response.status(HttpResponseStatus.CREATED.code())
.send()
}
}
protected Observable<Data> saveJsonAsData(GroovyContext context, String id) {
context.request.body.observe()
.map { TypedData typedData -> extractData(context, typedData) }
.doOnNext { Data data ->
data.id = id
validatorWrapper.validate(data)
}
.flatMap(data.&save as Func1)
.doOnError { Throwable throwable -> log.error("Error saving data", throwable) }
}
The issue is not so much with Rx as it is with the usage of the Context.
You should try to keep the response handling logic within your Handler, that is don't pass the Context around, rather get the objects you need and pass them to your services.
As an example
path('myendpoint') { MyRxService service ->
byMethod {
get {
// do something when request is GET
}
post {
request.body.map { typedData ->
extractItem(typeData) // extract your item from the request first
}.flatMap { item ->
service.saveJsonAsItemLocation(item).promiseSingle() // then once it's extracted pass the item to your "saveJsonAsItemLocation" method
}.then { ItemLocationStore updatedItem ->
response.headers.add(HttpHeaderNames.LOCATION, "/itemloc/v1/save/${updatedItem.tcin}/${updatedItem.store}")
context.response.status(HttpResponseStatus.CREATED.code()).send()
}
}
}
}
My guess is that you have something like this:
get {
// get stuff
}
post {
// post stuff
}
The reason this doesn't work is that Ratpack doesn't use Routing Table for handling incoming requests, instead it uses chain delegation. The get {} binds to root path and GET http method and post {} binds to root path and POST http method. Because get {} matches the path, Ratpack considers the handler matched and since the handler is for GET it considers it a 405.
There are chain methods available that binds regardless of HTTP Method such as all {} and path {}. Chain#all will handle all paths and methods where as Chain#path(String) matches against specific path.
Hope this helps.