Giter VIP home page Giter VIP logo

grails-rxjava's Introduction

RxJava for Grails

RxJava is a popular library for composing asynchronous and event-based programs by using observable sequences.

RxJava helps you build reactive applications and an increasing number of libraries take advantage of RxJava as the defacto standard for building Reactive applications.

In GORM 6.0, a new implementation of GORM called RxGORM has been introduced that builds on RxJava helping you building reactive data access logic using the familiar GORM API combined with RxJava.

This plugin helps integrate RxJava with the controller layer of Grails to complete the picture and enable complete end-to-end integration of RxJava with Grails.

Installation

To install the plugin declare a dependency in build.gradle:

dependencies {
    ...
    compile 'org.grails.plugins:rxjava:{version}'
}

Where {version} is the version of the plugin.

Documentation

For further information see the the User guide.

grails-rxjava's People

Contributors

aaloise avatar graemerocher avatar hardyrex avatar sbearcsiro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grails-rxjava's Issues

Upgrade RxJava

Any chance to upgrade or create a separate branch to RxJava 2?

Response Encoding for Stream (Server Sent Events)

Shouldn't rx.stream set the response encoding to UTF-8?

The Server Sent Events spec says:

Event streams are always decoded as UTF-8.

But I get an non UTF-8 encoded stream/response (with Apache Tomcat 8.0). I have to explicitly call response.setCharacterEncoding("UTF-8") in my Controller Action before returning rx.stream.

In my case Apache uses his default encoding of ISO8859-1.

Exception running example

I tried with Java 7 and 8, grails 3.2.5.

groovy.lang.MissingMethodException: No signature of method: grails.rx.web.helper.RxHelper.event() is applicable for argument types: (java.util.LinkedHashMap, grails.converters.JSON) values: [[id:0, comment:hello], {"type":"observable","num":0}]
Possible solutions: event(groovy.lang.Closure), event(groovy.lang.GString), event(groovy.lang.Writable), event(java.lang.CharSequence), event(java.util.Map), event(org.codehaus.groovy.runtime.GStringImpl)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at rxjava.demo.TickTockController$_observable_closure5.doCall(TickTockController.groovy:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1426)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at groovy.lang.Closure.call(Closure.java:414)
at rxjava.demo.TickTockController$_observable_closure5.call(TickTockController.groovy)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124)
at com.sun.proxy.$Proxy97.apply(Unknown Source)
at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:103)
at io.reactivex.internal.observers.DisposableLambdaObserver.onNext(DisposableLambdaObserver.java:58)
at io.reactivex.internal.operators.observable.ObservableInterval$IntervalObserver.run(ObservableInterval.java:83)
at io.reactivex.internal.schedulers.ScheduledDirectPeriodicTask.run(ScheduledDirectPeriodicTask.java:39)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:748)

Include Flowable as an option in 2.x

Since RxJava 2.x, Observables are no longer aware of backpressure. Grails RxJava plugin uses Observables in both branches (1.x and 2.x) which might lead do different behaviour depending on the use case.

http://www.nurkiewicz.com/2017/08/1x-to-2x-migration-observable-vs.html

It would be interesting if in the 2.x branch, Flowable can be an extra option living side by side with the current Observable solution, so one can choose which of both would better fit in it's particular needs. I believe that this can be a real benefit for the plugin and in some scenarios around this request/response approach.

RxResultSubscriber log noise: Broken pipe

RxResultSubscriber is logging an error at line 275 : log.error("Async Dispatch Error: ${e.message}", e).

When the user refreshes the browser, we see the following error with a large stack-trace:
2019-01-29 18:53:56.423 ERROR 6174 --- [ http-nio-8080-exec-4] o.g.plugins.rx.web.RxResultSubscriber : Async Dispatch Error: Broken pipe

However in line 278 it is using a debug level: log.debug("Async timeout occurred"). In both cases it seems that it is recovering from the error, and executing two lines of code:

asyncContext.request.removeAttribute(WebAsyncUtils.WEB_ASYNC_MANAGER_ATTRIBUTE) asyncContext.complete()

It seems that the system is recovering from above error conditions (in our use case we don't lose any event to the client, perhaps because the communication is being retried or established using a new connection). We would like to change the logging level to debug for both cases, just to avoid the log noise.

A thrown exception in rx.stream(Closure) does not close the event stream connection

This occurs in the default Tomcat in Grails 3.2.5 though I suspect it will occur in all previous Tomcat versions as well. It appears that the Catalina AsyncContextImpl does not handle an exception thrown by the Runnable passed to start(), so no AsyncListeners are notified. I'm not sure whether this is a bug in Tomcat or not (my Google-fu didn't turn up whether AsyncContext.start() was supposed to notify any listeners).

See a demo here: https://github.com/sbearcsiro/grailsrxdemo. I would expect the EventSource should close and reconnect on the client after the Exception is thrown. Note also that a unit test won't display this problem as the Spring MockAsyncContext executes the start() call on the same thread, so the exception bubbles back into the RxJava Observable which does call onError with the exception.

It seems to me that in the case of a NewObservableResult argument to the RxResultTransformer it should, by default, subscribe on the AsyncContext.start() thread. This would match the behaviour if an Observable is passed in. PR incoming...

No signature of method: grails.rx.web.helper.RxHelper.event() is applicable for argument types: (java.util.LinkedHashMap, grails.converters.JSON)

grails 3.3.0 , java 8 , default url

ERROR org.grails.plugins.rx.web.RxResultSubscriber - Async Dispatch Error: No signature of method: grails.rx.web.helper.RxHelper.event() is applicable for argument types: (java.util.LinkedHashMap, grails.converters.JSON) values: [[id:0, comment:hello], {"type":"observable","num":0}]
Possible solutions: event(groovy.lang.Closure), event(groovy.lang.GString), event(groovy.lang.Writable), event(java.lang.CharSequence), event(java.util.Map), event(org.codehaus.groovy.runtime.GStringImpl)
groovy.lang.MissingMethodException: No signature of method: grails.rx.web.helper.RxHelper.event() is applicable for argument types: (java.util.LinkedHashMap, grails.converters.JSON) values: [[id:0, comment:hello], {"type":"observable","num":0}]
Possible solutions: event(groovy.lang.Closure), event(groovy.lang.GString), event(groovy.lang.Writable), event(java.lang.CharSequence), event(java.util.Map), event(org.codehaus.groovy.runtime.GStringImpl)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:58)
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:54)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133)
at rxjava.demo.TickTockController$_observable_closure5.doCall(TickTockController.groovy:75)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1426)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:294)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1024)
at groovy.lang.Closure.call(Closure.java:414)
at rxjava.demo.TickTockController$_observable_closure5.call(TickTockController.groovy)
at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:54)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124)
at com.sun.proxy.$Proxy98.apply(Unknown Source)
at io.reactivex.internal.operators.observable.ObservableMap$MapObserver.onNext(ObservableMap.java:59)
at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onNext(ObservableDoOnEach.java:103)
at io.reactivex.internal.observers.DisposableLambdaObserver.onNext(DisposableLambdaObserver.java:58)
at io.reactivex.internal.operators.observable.ObservableInterval$IntervalObserver.run(ObservableInterval.java:83)
at io.reactivex.internal.schedulers.ScheduledDirectPeriodicTask.run(ScheduledDirectPeriodicTask.java:39)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.