I need to bring some data into an IObservable stream. I want to use an extension method on IObservable to do this, but i am not sure how to do it.
The data is produced by a simple class that has this signature:
interface Process<TIn, TOut> {
void Do(TIn data);
event Action<TOut> Result;
}
i.e. to start the process I have to call Do(...) and the result is sent to the event Result(...). This can't be changed!
I want to bring this data into an Rx process, that handles user input in this way:
subject.AsObservable<string> // this produces the observable of user inputs
.Throttle(TimeSpan.FromMilliseconds(typingDelay))
.DistinctUntilChanged()
.Process(myProcess) // this is what I need help for
.Switch()
.Subscribe(myConsumer)
This is from adopted from the standard example of delayed user input triggering a web service (or something else that is long-running and has to be async) in the Hands-on Labs.
Whenever the user continues to enter, all observables that are still "underway" must be cancelled (therefore the Switch()). So my Process() has to return an IObservable<IObservable<TOut>> to make the switch work correctly.
I'm really stuck here. Does anyone has a hint for me how to write this Process(...) extension method?
I've modified your Process interface to use generics properly and provided a dummy implementation of the interface like so:
interface IProcess<T, R>
{
void Do(T data);
event Action<IEnumerable<R>> Result;
}
public class ProcessImpl<T, R> : IProcess<T, R>
{
public void Do(T data) { }
public event Action<IEnumerable<R>> Result;
}
Now you can write the extension method like this:
public static IObservable<IObservable<R>> Process<T, R>(this T #this)
{
return Observable.Create<IObservable<R>>(o =>
{
var p = new ProcessImpl<T, R>();
var subscription =
Observable
.FromEvent<IEnumerable<R>>(
h => p.Result += h,
h => p.Result -= h)
.Take(1)
.Select(x => x.ToObservable())
.Subscribe(o);
p.Do(#this);
return subscription;
});
}
Does this work for you?
Basically, your Process extension method needs to subscribe to the source observable and output another. Something like:
public static IObservable<TOut> Process<TIn, TOut>(this IObservable<TIn> source, IProcess<TIn, TOut> processor)
{
return Observable.Create((IObserver<TOut> obs) =>
{
var sourceSub = source.Subscribe(processor.Do);
var outSub = Observable.FromEvent<TOut>(h => processor.Result += h,
h => processor.Result -= h)
.Subscribe(obs);
return new System.Reactive.Disposables.CompositeDisposable(sourceSub, outSub);
});
}
I don't think that Switch will do what you are hoping it will. All Switch will do is end one subscription when another observable becomes available. However, ending the subscription cannot cancel any running calls to the interface method Process.Do. The cancellation you are talking about will need to be handled by the interface implementation itself.
Related
In a Controller-Service-Datalayer architecture, I'm searching for a way to verify that my controller methods perform exactly one call to the service layer like this:
#DeleteMapping(value = "/{id}")
public ResponseEntity<String> deleteBlubber(#PathVariable("id") long blubberId) {
service.deleteBlubber(blubberId);
return new ResponseEntity<>("ok", HttpStatus.OK);
}
This should not be allowed:
#DeleteMapping(value = "/{id}")
public ResponseEntity<String> deleteBlubber(#PathVariable("id") long blubberId) {
service.deleteOtherStuffFirst(); // Opens first transaction
service.deleteBlubber(blubberId); // Opens second transaction - DANGER!
return new ResponseEntity<>("ok", HttpStatus.OK);
}
As you can see from the comments, the reason for this is to make sure that each request is handled in one transaction (that is started in the service layer), not multiple transactions.
It seems that ArchUnit can only check meta-data from classes and methods and not what's actually going on in a method. I would have to be able to count the request to the service classes, which seems to not be possible in ArchUnit.
Any idea if this might be possible? Thanks!
With JavaMethod.getMethodCallsFromSelf() you have access to all methods calls of a given method. This could be used inside a custom ArchCondition like this:
methods()
.that().areDeclaredInClassesThat().areAnnotatedWith(Controller.class)
.should(new ArchCondition<JavaMethod>("call exactly one service method") {
#Override
public void check(JavaMethod item, ConditionEvents events) {
List<JavaMethodCall> serviceCalls = item.getMethodCallsFromSelf().stream()
.filter(call -> call.getTargetOwner().isAnnotatedWith(Service.class))
.toList();
if (serviceCalls.size() != 1) {
String message = serviceCalls.stream().map(JavaMethodCall::getDescription).collect(joining(" and "));
events.add(SimpleConditionEvent.violated(item, message));
}
}
})
I am creating a j2me application which is interacting with a database on a server. Therefore I launch a thread to connect to the server. I handle all my command actions in a separate class which implements CommandListener.
When I try to get the response the server returned I get an empty String. I have tried waiting for the thread that connects to the server to return but this makes the application unresponsive.
Below is the code I am using.
//my network worker class.
public class NetworkConnector implements Runnable {
//constructor
public NetworkConnector(String url){
//url =>server url to connect to.
Thread thread = new Thread(this);
thread.start();
}
private String serverReply="";
private String url="
//method to connect to the server and return the
//response from the server.
public String sendData(String serverUrl) {
//open streams to connect to the Server.
httpConn = (HttpConnection)
Connector.open(serverUrl,Connector.READ_WRITE, true);
httpConn.setRequestMethod(HttpConnection.GET);
inStream = httpConn.openInputStream();
int read;
while ((read = inStream.read()) != -1) {
sb.append((char) read);
}
return sb.toString();
}
public String getServerReply() {
//serverReply is a class variable.
return serverReply;
}
public void run(){
//call the send method that connects to the server.
serverResponse = sendData(Url);
}
} //end of connector class.
// this class is where all my Command Actions are
//implemented.
public class CommandActionController implements
CommandListener, DataReceiver {
public void commandAction(Command cmd, Displayable d) {
//networkMgr => is the worker class that makes
//connection to the server.
networkMgr = new NetworkConnector("http://localhost
/JsonPhp/login.php?uname=" + loginUserInfo.userName +
"&passwd=" + loginUserInfo.password);
//here am getting the response from the server.
String serverResponse = networkMgr.getServerReply();
//at this point the ServerReponse String is Empty =>
//yet the server is supposed to return some String.
System.out.println("xxxxxxxxxxxxxxxxxx
ServerResponse =" + serverResponse);
}
}//end of CommandListener class.
Your expectations about serverResponse value are wrong; it can be empty at the moment when you attempt to obtain it in commandAction with the code snippet in the question.
In order to get non-empty value, you need to redesign method NetworkConnector.getServerReply() to make it properly wait until thread finishes and server response is indeed obtained.
If you do that, however, you will also have to redesign CommandActionController to keep user interface responsive - your testing with "waiting for the thread that connects to the server" has shown just that.
Redesigned code should just launch the server connect thread and exit the commandAction as soon as possible (possibly changing to some "wait screen" to let user see what happens). Next screen update should be triggered only after server response is obtained.
Consider studying a tutorial specifically targeted on explaining how to properly design this kind applications - Networking, User Experience, and Threads:
This article explains how your MIDlet can make network connections without compromising your user interface. It includes six iterative examples that illustrate multithreaded networking and the use of a wait screen...
Here is how I'd do without java.util.concurrent:
Result handleRequest(){
final String url = // get url
Work work = new Work(url):
Thread t = new Thread(work);
t.start();
// do other stuff
if(t.isAlive()){
// still running
}
// this waits until the work is done
// and it will be safe to access work.result after
// this call has returned.
t.join();
return work.result;
}
and then
class Work implements Runnable{
final String url;
Result result;
public void run(){
this.result = // do your network stuff
}
}
You shouldn't start a thread in the constructor. Also, runnable are meant to be passed to threads. The easiest (and the "proper") way of doing this would be as follows:
Implement a Callable instead of a Runnable.
Use a ExecutorService instead of a Thread
Use Future object to do the processing asynchronously/be responsive to user
Here is a simple example.
class Stuff {
final ExecutorService exec =
Executors.newCachedExecutorService(// please see doc);
Result process(String url){
Future<Result> future = exec.submit(new Work(url));
// do some other stuff
if(future.isDone()){
// return result?
}
return future.get(); // this call will wait until result is available
}
}
and then
class Work implements Callable<Result> {
final String url;
Result call() throws Exception {
// do your network stuff here
return result;
}
}
See documentation of java.util.concurrent.ExecutorService.submit(), java.util.concurrent.Future and java.util.concurrent.Callable for details.
I have a small iOS app (written using monotouch) which I'm wanting to bring over monodroid. The port is causing a couple of issues, some of which are down to the way the two platforms go about doing the UI and creating classes around them.
In the iOS app there is code like this
private void BtnSomething_TouchUpInside (object sender, EventArgs e)
{
string f = this.foo;
LGPM gpm = new LGPM(Constants.a, Constants.b, f);
this.auth = new Auth("cheese", gpm);
(*) this.auth.TokenReceived += (o, e, a, aTS, r) => {
// more stuff here
};
this.PresentModalViewController(this.auth, true);
}
the auth class looks like this
public partial class Auth
{
public Auth(string m, data d)
{
this.d = d;
this.m = m;
}
// create a UIWebView and do things
Upshot - auth creates the webview, does things and returns control back to the (*) line
For monodroid, things are different as you can't really create classes like that. The best I've come up with is this
private void BtnSomething_TouchUpInside (object sender, EventArgs e)
{
string f = this.foo;
LGPM gpm = new LGPM(Constants.a, Constants.b, f);
this.auth = new Auth("cheese", gpm, context);
(*) this.auth.TokenReceived += (o, e, a, aTS, r) => {
// more stuff here
};
this.PresentModalViewController(this.auth, true);
}
then in the Auth class
public class Auth : Application
{
public Auth(string m, data d, Context c)
{
this.d = d;
this.m = m;
Intent t = new Intent(this, typeof(webview));
t.PutExtra("todo", 1);
c.StartActivity(t);
}
}
[Activity]
It's then a "normal" webview activity.
This seems to work, however, control is not return to the (*) line once the webview has completed.
The webview itself is performing an async grab of data from a website (called AuthToken), which causes an event to be thrown once it's done. I'm not sure if it's down to the difference in how classes and activities are written between the two, but in the iOS version, the event is triggered, in the Android version, it's missed.
This leads me to wonder if the way the platforms differ in how they deal with async events. Is there a tutorial somewhere on the difference between how the two platforms deal with async events?
Lots of questions I know, but threading and async events are important.
Thanks
Use startActivityForResult or another Android-ism to get the thread after some processing event.
I have the following (here simplified) code which I want to test with FakeItEasy.
public class ActionExecutor : IActionExecutor
{
public void TransactionalExecutionOf(Action action)
{
try
{
// ...
action();
// ...
}
catch
{
// ...
Rollback();
}
}
public void Commit()
{ }
public void Rollback()
{ }
}
public class Service : IService
{
private readonly IRepository _repository;
private readonly IActionExecutor _actionExecutor;
// ctor for CI
public void ServiceMethod(string name)
{
_actionExecutor.TransactionalExecutionOf(() =>
{
var item = _repository.FindByName(ItemSpecs.FindByNameSpec(name));
if (item == null) throw new ServiceException("Item not found");
item.DoSomething();
_actionExecutor.Commit();
}
}
}
I want to test that the ServiceException is thrown so i setup my test like that
var repo = A.Fake<IRepository>();
A.CallTo(() => repo.FindByName(A<ISpec<Item>>.Ignored))
.Returns(null);
var executor = A.Fake<IActionExecutor>();
executor.Configure()
.CallsTo(x => x.Rollback()).DoesNothing();
executor.Configure()
.CallsTo(x => x.Commit()).DoesNothing();
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
With the following code
var service = new Service(executor, repo);
service.ServiceMethod("notExists")
.Throws(new ServiceException());
I get the following message
The current proxy generator can not intercept the specified method
for the following reason:
- Sealed methods can not be intercepted.
If I call the method directly on the service like
var service = new Service(executor, repo);
service.ServiceMethod("NotExists");
I get this message
This is a DynamicProxy2 error: The interceptor attempted to 'Proceed'
for method 'Void TransactionalExecutionOf(System.Action)' which has no
target. When calling method without target there is no implementation
to 'proceed' to and it is the responsibility of the interceptor to
mimic the implementation (set return value, out arguments etc)
Now I am a bit confused and don't know what to do next.
Problems comes from the way you create fake and what you later expect it to do:
var executor = A.Fake<IActionExecutor>();
// ...
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
What base method? FakeItEasy has no idea what the base class is, and hence the DynamicProxy2 exception in your second case. You can create partial mock this way:
var executor = A.Fake<ActionExecutor>();
Note that we're basing on actual implementation, not interface anymore
This however introduces a new set of problems, as methods on ActionExecutor are not virtual and therefore interceptor cannot hook up to well - intercept them. To make your current setup work, you'll have to change your ActionExecutor and make (all) the methods virtual.
However, you may (or even should) want to avoid modifications of existing code (which sometimes might not even be an option). You could then set up your IActionExecutor fake like this:
var executor = A.Fake<IActionExecutor>();
A.CallTo(() => executor.TransactionalExecutionOf(A<Action>.Ignored))
.Invokes(f => new ActionExecutor()
.TransactionalExecutionOf((Action)f.Arguments.First())
);
This will allow you to work on faked object, with the exception of call to TransactionalExecutionOf which will be redirected to actual implementation.
Silverlight can only send a certain number of simultaneous WCF requests at a time. I am trying to serialize the requests that a particular section of my application is performing because I don't need them to run concurrently.
The problem is as follows (summary below):
"WCF proxies in Silverlight applications use the SynchronizationContext of the thread from which the web service call is initiated to schedule the invocation of the async event handler when the response is received. When the web service call is initiated from the UI thread of a Silverlight application, the async event handler code will also execute on the UI thread."
http://tomasz.janczuk.org/2009/08/improving-performance-of-concurrent-wcf.html
summary: basically, if you block the thread that is calling the async method, it will never get called.
I can't figure out the right model of threading this such which would give me what I want in a reasonable way.
My only other requirement is that I don't want the UI thread to block.
As far as I can see, what should work is if the UI thread has a worker thread which queues up the calls as Action delegates, then uses an AutoResetEvent to execute a task one at a time in yet another worker thread. There are two problems:
1) The thread that calls async can't block, because then async will never get called. In fact, if you put that thread into a wait loop, I've noticed it doesn't get called either
2) You need a way to signal from the completed method of the async call that it is done.
Sorry that was so long, thanks for reading. Any ideas?
I have used a class that i build on my own to execute load operations synchronous. With the class you can register multiple load operations of diffrent domaincontexts and then execute them one by one. You can provide an Action to the constructor of the class that gets called, when all operations are finished (successful or failed).
Here´s the code of the class. I think it´s not complete and you have to change it to match your expectations. Maybe it can help you in your situation.
public class DomainContextQueryLoader {
private List<LoadOperation> _failedOperations;
private Action<DomainContextQueryLoader> _completeAction;
private List<QueuedQuery> _pendingQueries = new List<QueuedQuery>();
public DomainContextQueryLoader(Action<DomainContextQueryLoader> completeAction) {
if (completeAction == null) {
throw new ArgumentNullException("completeAction", "completeAction is null.");
}
this._completeAction = completeAction;
}
/// <summary>
/// Expose the count of failed operations
/// </summary>
public int FailedOperationCount {
get {
if (_failedOperations == null) {
return 0;
}
return _failedOperations.Count;
}
}
/// <summary>
/// Expose an enumerator for all of the failed operations
/// </summary>
public IList<LoadOperation> FailedOperations {
get {
if (_failedOperations == null) {
_failedOperations = new List<LoadOperation>();
}
return _failedOperations;
}
}
public IEnumerable<QueuedQuery> QueuedQueries {
get {
return _pendingQueries;
}
}
public bool IsExecuting {
get;
private set;
}
public void EnqueueQuery<T>(DomainContext context, EntityQuery<T> query) where T : Entity {
if (IsExecuting) {
throw new InvalidOperationException("Query cannot be queued, cause execution of queries is in progress");
}
var loadBatch = new QueuedQuery() {
Callback = null,
Context = context,
Query = query,
LoadOption = LoadBehavior.KeepCurrent,
UserState = null
};
_pendingQueries.Add(loadBatch);
}
public void ExecuteQueries() {
if (IsExecuting) {
throw new InvalidOperationException("Executing of queries is in progress");
}
if (_pendingQueries.Count == 0) {
throw new InvalidOperationException("No queries are queued to execute");
}
IsExecuting = true;
var query = DequeueQuery();
ExecuteQuery(query);
}
private void ExecuteQuery(QueuedQuery query) {
System.Diagnostics.Debug.WriteLine("Load data {0}", query.Query.EntityType);
var loadOperation = query.Load();
loadOperation.Completed += new EventHandler(OnOperationCompleted);
}
private QueuedQuery DequeueQuery() {
var query = _pendingQueries[0];
_pendingQueries.RemoveAt(0);
return query;
}
private void OnOperationCompleted(object sender, EventArgs e) {
LoadOperation loadOperation = sender as LoadOperation;
loadOperation.Completed -= new EventHandler(OnOperationCompleted);
if (loadOperation.HasError) {
FailedOperations.Add(loadOperation);
}
if (_pendingQueries.Count > 0) {
var query = DequeueQuery();
ExecuteQuery(query);
}
else {
IsExecuting = false;
System.Diagnostics.Debug.WriteLine("All data loaded");
if (_completeAction != null) {
_completeAction(this);
_completeAction = null;
}
}
}
}
Update:
I´ve just noticed that you are not using WCF RIA Services, so maybe this class will not help your.
There are some options:
- You can take a look at the Agatha-rrsl either by inspecting the implementation of it or by just using it instead of pure wcf. The framework allows you to queue requests. You can read more here.
- Another option is to use the Reactive extension. There is a SO example here and more info here and here.
- You can try the Power Thread library from Jeffrey Richter. He describes it on his book CLR via C#. You can find the library here. This webcast gives you some info about it.
- You can always roll your own implementation. The yield statement is a good help here. Error handling makes it very difficult to get the solution right.