When using the Room library for Android the documentation clearly states that we cannot make calls on the main thread unless we specifically allow them. What I'm curious about is methods that have a void return type. It seems silly that returning LiveData will automatically run them off the main thread, but void types will not (unless I'm missing something). Is there any easy way I can do this without having to run this in my own managed thread?
My Query:
#Dao
interface UserDao {
#Query("DELETE FROM users")
fun clear()
}
I've even tried using Kotlin reflection + extension functions, but this seemed to fail during runtime:
fun KFunction<Unit>.execOn(executor: Executor, vararg args: Any?) {
executor.execute {
this.call(args)
}
}
Then make a call like:
myDb.userDao()::clear.execOn(diskExecutor)
Note what does work is:
diskExecutor.execute {
myDb.userDao().clear()
}
It seems silly that returning LiveData will automatically run them off the main thread, but void types will not (unless I'm missing something).
Without some sort of annotation, Room would have no idea that you want a void-returning DAO method to be run on a background thread. With a reactive return type (e.g., LiveData, Single), you are explicitly requesting background execution, so no additional metadata (e.g., an annotation) is required.
You might consider filing a feature request for such an annotation-based approach.
Is there any easy way I can do this without having to run this in my own managed thread?
If you are asking "does Room have a background-execution option for DAO methods other than those with reactive return types?", then the answer is no, at least at the present time.
Related
I'm aware it's a complex question that cannot have a definite answer without posting a few hundreds of lines of code, which is why I'm looking for help through general ideas and pointers.
I have a Room #Query returning a RxJava3 Flowable<List<...>> which I subscribe to on RxJava thread Schedulers.io(), and observe from an activity-scoped ViewModel on RxJava thread AndroidSchedulers.mainThread(). The data is then stored in my ViewModel as LiveData, which plays better than RxJava when it comes to handle Android components' lifecycle.
The idea is to have a clean and immediate data update pattern, not to have to handle disposal and re-subscription separately on each activity or fragment lifecycle event such as onPaused and onResumed, and being updated in the background even when my activity is hidden in order to avoid that awful refresh lag when returning to my activity. I was pretty amazed at that design pattern. I still am, but I'm beginning to have doubts.
When starting another activity with the same design pattern, I do change a value and immediately get an updated List<...> from the other ViewModel. Different Activity, different ViewModel, same design, same database table. When returning to the first Activity, I find that the new data does never get updated: Room did not emit any update even though the data set has changed. I have to dispose and subscribe again in order to see the new data.
So my question is: any pointer on where the source of my problem might be?! Is there something rotten in the core of this design pattern? Something I misunderstood about all those things are supposed to work together? Is it just a mistake of mine due to some threading issue? Or should I fill a bug report for Room?
I tried to observe another non-Room RxJava3 observable from the ViewModel of my first Activity, and it does get updates when its data set is updated.
By the way, I also use Hilt in order to inject eveything as #Singleton.
Thank you for your time :-)
After a week of headaches, I have finally stumbled upon a solution, which happens to be clean and elegant.
The issue was RxJava, which, I just learnt, is not supposed to seamlessly handle multiple subscriptions to the same Observable. The solution is supposedly to make use of the publish(), connect(), refcount() operators, or better use the shortcut share(). I tried every way I could think of, without success (it actually made it worse). I also tried to subscribe() to the Room Flowable from my repository and proxy it through a BehaviorSubject.
There was this weird org.reactivestreams.Publisher in Room's documentation, whose added value I wouldn't know, and whose origin wasn't even my familiar io.reactivex.rxjava3. It turns out it that was the solution. Edit: It turns out Publisher is an interface that Flowable happens to implement.
build.gradle
implementation 'android.arch.lifecycle:reactivestreams:+'
Dao.java
#Query("...")
Flowable<List<...>> getFlowable();
ViewModel.java
public liveData;
#Inject
public ViewModel(#NonNull RoomDatabase roomDatabase) {
liveData = LiveDataReactiveStreams.fromPublisher(roomDatabase.dao().getFlowable());
}
It seems too easy to be true, but as far as I can see it seems to work perfectly better this way.
Edit:
It turns out the root of this issue was a slight little bit more vicious than I thought. I assumed #InstallIn(SingletonComponent.class) in my dependency injection #Module was enough, but apparently a #Singleton annotation on each #Provides method is also required.
#Module
#InstallIn(SingletonComponent.class)
public abstract class DependencyInjection
{
#Provides
#NonNull
#Singleton // do not omit this
public static DataDao provideDataDao(#NonNull RoomDatabase roomDatabase) {
return roomDatabase.dataDao();
}
#Provides
#NonNull
#Singleton // do not omit this
public static RoomDatabase provideRoomDatabase(#ApplicationContext Context applicationContext) {
return
BuildConfig.DEBUG ?
Room.databaseBuilder(applicationContext, RoomDatabase.class, "playground.db").fallbackToDestructiveMigration().build() :
Room.databaseBuilder(applicationContext, RoomDatabase.class, "playground.db").build() ;
}
}
I am starting a new project and am thinking of using Simple Injector interception (https://simpleinjector.readthedocs.io/en/latest/InterceptionExtensions.html) for tracing method entry/exit and logging parameters and return values etc. I have used this interceptor in the past and it works great. But my previous projects were not async/await. This new project has a lot of methods that are all async/await and I was wondering
will this interceptor work for async/await methods?
what changes are required in this interceptor to make it work for async/await methods?
I understand that decorators are a much better pattern than interception but writing a decorator for each and every interface that I want to trace is not something that I am looking forward to doing.
UPDATE:
I have tried this interceptor in my async/await code and it does inject my tracing code. However, I was getting weird results in some parts of my application. I didn't get chance to dig deeper into why disabling interception would make it work fine and why when interception was enabled it would not work as expected. It could very well be something wrong with my code.
I was hoping if someone, who has already used this interception extension in their code, would be able to point me in the right direction.
will this interceptor work for async/await methods?
Async code in C# is syntactic sugar on top of Task. This means that if your code needs to do anything useful after a call to an async method, you will have call ContinueWith on the returned Task (or use the C# syntax). If you take asynchronous into consideration in your interceptor, you won't be able to execute logic after the wrapped object.
So to make this work, you will have to explicitly check whether the wrapped method returns Task and if that's the case, you should make things async by hooking your 'after' code using ContinueWith.
This is one of the many reasons I consider interception to be inferior to using decorators. Decorators allow your code to be much cleaner, refrain from using reflection, give complete compile time support, give better performance, prevent having to depend on an interception library, and force you into a much more SOLID application design.
That said, the documentation's MonitoringInterceptor will look as follows when it takes asynchronicity into consideration:
class MonitoringInterceptor : IInterceptor
{
private readonly ILogger logger;
public MonitoringInterceptor(ILogger logger) {
this.logger = logger;
}
public void Intercept(IInvocation invocation) {
var watch = Stopwatch.StartNew();
// Calls the decorated instance.
invocation.Proceed();
var task = invocation.ReturnValue as Task;
if (task != null) {
invocation.ReturnValue = LogElapsedAsync(task, invocation, watch);
} else {
LogElapsed(invocation, watch);
}
}
private async Task LogElapsedAsync(Task task, IInvocation i, Stopwatch w) {
await task;
LogElapsed(i, w);
}
private void LogElapsed(IInvocation invocation, Stopwatch watch) {
var decoratedType = invocation.InvocationTarget.GetType();
this.logger.Log(string.Format("{0} executed in {1} ms.",
decoratedType.Name, watch.ElapsedMilliseconds));
}
}
Grails users know that Data access layer of this framework offer an AOP programming via seperation cross-layer from other soft layers : afterInsert, afterUpdate,beforeInsert .... methods .
class Person{
def afterInsert(){
//... Will be executed after inserting record into Person table
}
}
I search on the type of this methods vis-a-vis Constructor(instantiation ): Asynchronous or not . And i don't find the answer .
My question : if not, Does GORM will be breaked if we force those methods to be asynchronous.
UPDATE :
Indeed, we want send mails without using a ready plugin as we have our own API.
There are a great number of ways to accomplish what you are looking for, and without knowing all your requirements it's difficult to give you a solution that meets all of them. However, based on your question and the comments provided you could use the built in Asynchronous features in Grails to accomplish this.
This is just a sketch/example of something I came up with off the top of my head.
import static grails.async.Promises.*
class Person {
...
def afterUpdate() {
def task1 = task {
// whatever code you need to run goes here.
}
onComplete([task1]) {
// anything you want to run after the task completes, or nothing at all.
}
}
...
}
This is just one option. Again, there are a lot of options available to you. You could send a JMS message instead and have it processed on a different machine. You could use some type of eventing system, you could even use Spring AOP and Thread pools and abstract this even further. It depends on what your requirements are, and what your capabilities are as well.
Im designing a small library and sometimes i write a couple lines and it just doesn't feel right, so i'd like to get the opinions/advices of an experimented java programmer.
Ive got a listener which handle 3 differents events and in one of my class I implement the methods that will actually fire the events
So what i did at first was something like this:
protected final void fireOperationStarted(){
OperationEvent event = new OperationEvent(this);
for (OperationListener listener : listeners) {
listener.operationStarted(event);
}
}
protected final void fireOperationEnded(){
OperationEvent event = new OperationEvent(this);
for (OperationListener listener : listeners) {
listener.operationEnded(event);
}
//omitted the 3rd method on purpose
but this code felt wrong because if someone want to implement their own event, they will basically need access to the whole listener arraylist (CopyOnWriteArraylist) and write the logic again and again.
So what i opted for is a Fireable interface with a single method "fire". And this is what i've done:
protected final void fireOperationStarted(){
fireOperation(new Fireable(){
#Override
public void fire(OperationListener listener, OperationEvent event) {
listener.operationStarted(event);
}
});
}
protected final void fireOperationEnded(){
fireOperation(new Fireable(){
#Override
public void fire(OperationListener listener, OperationEvent event) {
listener.operationEnded(event);
}
});
}
protected void fireOperation(Fireable fireable){
OperationEvent event = new OperationEvent(this);
for (OperationListener listener : listeners) {
fireable.fire(listener, event);
}
}
I'd like to get your opinions, I personally think its better than the first implementation even there is still a lot of boilerplate code. Maybe there is a better way to do this ? I've looked in the java.awt.events package source code to see how they were dealing with multiple events and how they fire them, but it seem way too complicated for my needs.
One thing that i was wondering also is about the lambda expression in Java 8, if i use them without importing any Java 8 packages and i compile, will it work on the JRE7 ?
Could be great to use the JDK8 to make my codes cleaner eventually.
Thanks for your help !
I think your first example is better. listeners has got to be an instance field, and so readily available to everybody.
(You might have only one method in OperationListener and use a value in OperationEvent to determine which action is involved. Then your methods could all pass the proper event to one method that calls the one listener method.)
Your second idea is interesting, but for use inside one instance of one class, I think it's overkill.
There's all different kinds of ways to store listeners. If you're not adding and removing them too fast, ArrayList is good. If there's any chance of adding and removing them on different threads and you're calling the listeners frequently, CopyOnWriteArrayList is much better.
Don't worry too much about "boilerplate". Java tends to go with wordy-but-simple as regards low level code. The two for loops in your first example call out to be combined somehow, but it's not worth worrying about until you've got a lot more of them.
Lambdas will reduce your lines of code (if you use simple ones; my C# lambdas all end up running 20 lines or more; might as well be anonymous classes!), but they'll add plenty of pages to the language manual. However, lambdas aren't there till JRE 8.
I will explain with an example. My GWT project has a Company module, which lets a user add, edit, delete, select and list companies.
Of these, the add, edit and delete operations lands back the user on the CompanyList page.
Thus, having three different events - CompanyAddedEvent, CompanyUpdatedEvent and CompanyDeletedEvent, and their respective event handlers - seems overkill to me, as there is absolutely not difference in their function.
Is it OK to let a single event manage the three operations?
One alternative I think is to use some event like CompanyListInvokedEvent. However, somewhere I think its not appropriate, is the event actually is not the list being invoked, but a company being added/updated/deleted.
If it had been only a single module, I would have get the task done with three separate events. But other 10 such modules are facing this dilemma. It means 10x3 = 30 event classes along with their 30 respective handlers. The number is large enough for me to reconsider.
What would be a good solution to this?
UPDATE -
#ColinAlworth's answer made me realize that I could easily use Generics instead of my stupid solution. The following code represents an event EntityUpdatedEvent, which would be raised whenever an entity is updated.
Event handler class -
public class EntityUpdatedEvent<T> extends GwtEvent<EntityUpdatedEventHandler<T>>{
private Type<EntityUpdatedEventHandler<T>> type;
private final String statusMessage;
public EntityUpdatedEvent(Type<EntityUpdatedEventHandler<T>> type, String statusMessage) {
this.statusMessage = statusMessage;
this.type = type;
}
public String getStatusMessage() {
return this.statusMessage;
}
#Override
public com.google.gwt.event.shared.GwtEvent.Type<EntityUpdatedEventHandler<T>> getAssociatedType() {
return this.type;
}
#Override
protected void dispatch(EntityUpdatedEventHandler<T> handler) {
handler.onEventRaised(this);
}
}
Event handler interface -
public interface EntityUpdatedEventHandler<T> extends EventHandler {
void onEventRaised(EntityUpdatedEvent<T> event);
}
Adding the handler to event bus -
eventBus.addHandler(CompanyEventHandlerTypes.CompanyUpdated, new EntityUpdatedEventHandler<Company>() {
#Override
public void onEventRaised(EntityUpdatedEvent<Company> event) {
History.newItem(CompanyToken.CompanyList.name());
Presenter presenter = new CompanyListPresenter(serviceBundle, eventBus, new CompanyListView(), event.getStatusMessage());
presenter.go(container);
}
});
Likewise, I have two other Added and Deleted generic events, thus eliminating entire redundancy from my event-related codebase.
Are there any suggestions on this solution?
P.S. > This discussion provides more insight on this problem.
To answer this question, let me first pose another way of thinking about this same kind of problem - instead of events, we'll just use methods.
In my tiered application, two modules communicate via an interface (notice that these methods are all void, so they are rather like events - the caller doesn't expect an answer back):
package com.acme.project;
public interface CompanyServiceInteface {
public void addCompany(CompanyDto company) throws AcmeBusinessLogicException;
public void updateCompany(CompanyDto company) throws AcmeBusinessLogicException;
public void deleteCompany(CompanyDto company) throws AcmeBusinessLogicException;
}
This seems like overkill to me - why not just reduce the size of this API to one method, and add an enum argument to simplify this. This way, when I build an alternative implementation or need to mock this in my unit tests, I just have one method to build instead of three. This gets to be clearly overkill when I make the rest of my application - why not just ObjectServiceInterface.modify(Object someDto, OperationEnum invocation); to work for all 10 modules?
One answer is that you might want want to drastically modify the implementation of one but not the others - now that you've reduced this to just one method, all of this belongs inside that switch case. Another is that once simplified in this way, the inclination often to further simplify - perhaps to combine create and update into just one method. Once this is done, all callsites must make sure to fulfill all possible details of that method's contract instead of just the one specific one.
If the receivers of those events are simple and will remain so, there may be no good reason to not just have a single ModelModifiedEvent that clearly is generic enough for all possible use cases - perhaps just wrapping the ID to request that all client modules refresh their view of that object. If a future use case arises where only one kind of event is important, now the event must change, as must all sites that cause the event to be created so that they properly populate this new field.
Java shops typically don't use Java because it is the prettiest language, or because it is the easiest language to write or find developers for, but because it is relatively easy to maintain and refactor. When designing an API, it is important to consider future needs, but also to think about what it will take to modify the current API - your IDE almost certainly has a shortcut key to find all invocations of a particular method or constructor, allowing you to easily find all places where that is used and update them. So consider what other use cases you expect, and how easily the rest of the codebase can be udpated.
Finally, don't forget about generics - for my example above, I would probably make a DtoServiceInterface to simplify matters, so that I just declare the one interface with three methods, and implement it and refer to it as needed. In the same way, you can make one set of three GwtEvent types (with *Handler interfaces and possibly Has*Handlers as well), but keep them generic for all possible types. Consider com.google.gwt.event.logical.shared.SelectionEvent<T> as an example here - in your case you would probably want to make the model object type a parameter so that handlers can check which type of event they are dealing with (remember that generics are erased in Java), or source from one EventBus for each model type.