I have a simply interface:
public interface ITest
{
void Method1();
void Method2();
}
and implementation:
public class Test:ITest
{
public void Method1()
{
}
public void Method2()
{
//Method1();
}
}
The custom interceptor:
public class CustomInterceptor:IInterceptor
{
public void Intercept(IInvocation invocation)
{
invocation.Proceed();
}
}
Now, when I execute there two methods:
ITest obj = getting through ninject
obj.Method1();
obj.Method2();
my interceptor is calling twice what is ok.
But when I uncomment the body of Method2(), then the interceptor for the Method1() is not called. I'm looking for what to do, because I want the interceptor to be fired.
When I call the Method1 from the second, I understand this is not called by the generated proxy and that's why it doesn't work. But is it possible to do it in same way?
Ninject creates a proxy object around the actual instance of the Test class. Your methods aren't virtual, so any override for the proxy should be created with 'new' rather than 'override'. Thus, if you call Method1 from Method2, there is no virtual lookup to find the proxy and invoke it.
Related
In my integration test I'm using BlockHound to capture any blocking call.
For setting up the data I am doing a blocking call because I want the data to be persisted in the DB when running each test.
When running the integration test Blockhound is throwing an error at the set up method: reactor.blockhound.BlockingOperationError: Blocking call! java.io.FileInputStream#readBytes
How to avoid this?
#BeforeAll
public static void blockHoundSetup() {
BlockHound.install();
}
#BeforeEach
public void setUp() {
stagingAreaAdapter.deleteAll()
.thenMany(Flux.fromIterable(data))
.flatMap(stagingAreaAdapter::save)
.blockLast();
}
Check BlockHound customizations for allowing and disallowing blocking calls inside methods:
https://github.com/reactor/BlockHound/blob/master/docs/customization.md#dis-allowing-blocking-calls-inside-methods
1. using builder in a #BeforeAll method (as per #KrisKris1):
#BeforeAll
public static void blockHoundSetup() {
BlockHound.builder().allowBlockingCallsInside(
TestClass.class.getName(), "setUp").install();
}
or
2. via implementing the BlockHoundIntegration interface (still applies globally):
public class BlockHoundCustomConfiguration implements BlockHoundIntegration {
#Override
public void applyTo(BlockHound.Builder builder) {
builder.allowBlockingCallsInside("java.base/java.io.RandomAccessFile", "readBytes");
}
}
and create the following file:
<project dir>/src/test/resources/META-INF/services/reactor.blockhound.integration.BlockHoundIntegration
with your custom class:
com.example.config.BlockHoundCustomConfiguration
You need to allow blocking method calls inside java.util.zip.InflaterInputStream#read down the callstack.
Add in your BlockHound customization config.
public class ReactorBlockHoundIntegration implements BlockHoundIntegration {
#Override
public void applyTo(BlockHound.Builder builder) {
builder.allowBlockingCallsInside(InflaterInputStream.class.getName(), "read");
}
}
https://docs.oracle.com/javase/8/docs/api/index.html?java/util/zip/package-summary.html
I am trying to process a custom annotation on a class that implements an external interface that defines a Resource. The setup is the following:
A Resource interface, I can't modify it:
#Path("/v1")
public interface Resource {
#GET
#Path("/foo")
Response foo();
}
An implementation that I can modify:
public class ResourceImpl implements Resource {
#Override
#CustomAnnotation // has Retention.RUNTIME
public Response foo() {
// foo logic
}
}
I've implemented a filter to try and process the #CustomAnnotation on the overriden foo() method:
#Provider
#ServerInterceptor
#Precedence("SECURITY")
public class CustomAnnotationInterceptor implements ContainerRequestFilter {
#Context
ResourceInfo resourceInfo;
#Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
// check if the invoked resource method is annotated with #CustomAnnotation and do logic
}
}
However, when I try to get the matched resource class from the ResourceInfo instance, I get the Resource interface, and when I get the matched method, I get the foo() method from the interface which is lacking the #CustomAnnotation. Is there any way around this?
I'm using RESTEasy as an implementation of JAX-RS.
You could implement an interceptor, where you can get hold of the actual resource (method and class) being called. The interceptor should be bound to your annotation using #InterceptorBinding (see 54.2.4 Binding Interceptors to Components).
// Interceptor
#Interceptor
#CustomAnnotation
#Priority(Interceptor.Priority.APPLICATION)
public class CustomAnnotationInterceptor {
#AroundInvoke
public Object interceptCustomAnnotation(InvocationContext ctx) throws Exception {
CustomAnnotation customAnnotation = null;
// The actual method being called
Method method = ctx.getMethod();
if (method != null) {
customAnnotation = method.getAnnotation(CustomAnnotation.class);
}
// ... do stuff with the annotation
return ctx.proceed();
}
}
To get the instance of the class that implements your interface you could use ctx.getMethod().getDeclaringClass() or ctx.getTarget().getClass().getSuperclass().
How does a WCF channel (created via ChannelFactory) implement ICommunicationObject, but doesn't expose the Close() method, for example, unless you cast the proxy to ICommunicationObject? Does that make sense?
I got to thinking about that on the way home today and couldn't figure it out in my head. Maybe I'm asking the wrong question? Maybe I'm asking a stupid question? :)
Is it some kind of ninja trick?
This is done via Explicit Interface Implementation.
Suppose you have an interface, like so:
public interface IFoo
{
void Foo();
}
You can implement this normally:
public class Bar : IFoo
{
public void Foo() {} // Implicit interface implementation
}
Alternatively, you can implement the interface members explicitly, which requires the cast:
public class Baz : IFoo
{
void IFoo.Foo() {} // This will require casting the object to IFoo to call
}
This can be very useful at times. For example, it is often done to implement IDisposable in classes where the preferred API would be to call .Close(), for example. By implementing IDisposable explicitly, you "hide" the Dispose() method, but still allow the class instance to be used via a using statement.
The Channel class implements the ICommunicationObject interface explicitly. Here's an example demonstrating the difference between explicit interface implementation and implicit interface implementation:
internal interface IExample
{
void DoSomething();
}
class ImplicitExample : IExample
{
public void DoSomething()
{
// ...
}
}
class ExplicitExample : IExample
{
void IExample.DoSomething()
{
// ...
}
}
class Consumer
{
void Demo()
{
var explicitExample = new ExplicitExample();
// explicitExample.DoSomething(); <-- won't compile
((IExample)explicitExample).DoSomething(); // <-- compiles
var implicitExample = new ImplicitExample();
implicitExample.DoSomething(); // <-- compiles
}
}
Here is a link to the an MSDN article on this subject: http://msdn.microsoft.com/en-us/library/ms173157.aspx
I've been trying to get the ninject working in wcf, using the wcf extension and the interception with dynamicproxy2 extension. I've basically created a Time attribute and have it all working in a basic scenario. Where I get trouble is when in ninject module I create my service binding with a constructor argument:
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>().WithConstructorArgument("dependency", Kernel.Get<IMyDependency>());
Everything works fine, but the Time attribute wont fire on anything in my Service1 or MyDependency.
The time attribute is the standard one floating all over the internet. The only other piece of code really is the CreateKernel method is the global.asax, which looks like this:
protected override IKernel CreateKernel() {
IKernel kernel = new StandardKernel(
new NinjectSettings() { LoadExtensions = false },
new WcfNinjectModule(),
new DynamicProxy2Module()
);
return kernel;
}
Thanks for any help!
Matt
EDIT 12/12/2011: As requested, I've added some more detail below:
The entire wcf ninject module:
public class WcfNinjectModule : NinjectModule
{
public override void Load()
{
Bind<IMyDependency>().To<MyDependency>();
Bind<IService1>().To<Service1>();
}
}
The create kernel method in the global.asax is above, and the global.asax inherits from NinjectWcfApplication.
Service method looks like this:
public class Service1 : IService1
{
private IMyDependency _dependency;
public Service1()
{
}
public Service1(IMyDependency dependency)
{
_dependency = dependency;
}
[Time]
public virtual string GetData(string value)
{
return string.Format(_dependency.GetMyString(), value);
}
}
public interface IMyDependency
{
string GetMyString();
}
public class MyDependency : IMyDependency
{
[Time]
public virtual string GetMyString()
{
return "Hello {0}";
}
}
Does this help?
Since removing the 'WithConstructor' argument, the time intercept attribute will fire on GetMyString but not on GetData.
Matt
After a little more work (and writing that last post edit), it turns out that just removing the WithConstructorArgument method did resolve my problem and everything now seems to be working fine.
Matt
I have a service proxy class that makes asyn call to service operation. I use a callback method to pass results back to my view model.
Doing functional testing of view model, I can mock service proxy to ensure methods are called on the proxy, but how can I ensure that callback method is called as well?
With RhinoMocks I can test that events are handled and event raise events on the mocked object, but how can I test callbacks?
ViewModel:
public class MyViewModel
{
public void GetDataAsync()
{
// Use DI framework to get the object
IMyServiceClient myServiceClient = IoC.Resolve<IMyServiceClient>();
myServiceClient.GetData(GetDataAsyncCallback);
}
private void GetDataAsyncCallback(Entity entity, ServiceError error)
{
// do something here...
}
}
ServiceProxy:
public class MyService : ClientBase<IMyService>, IMyServiceClient
{
// Constructor
public NertiAdminServiceClient(string endpointConfigurationName, string remoteAddress)
:
base(endpointConfigurationName, remoteAddress)
{
}
// IMyServiceClient member.
public void GetData(Action<Entity, ServiceError> callback)
{
Channel.BeginGetData(EndGetData, callback);
}
private void EndGetData(IAsyncResult result)
{
Action<Entity, ServiceError> callback =
result.AsyncState as Action<Entity, ServiceError>;
ServiceError error;
Entity results = Channel.EndGetData(out error, result);
if (callback != null)
callback(results, error);
}
}
Thanks
Played around with this a bit and I think I may have what you're looking for. First, I'll display the MSTest code I did to verify this:
[TestClass]
public class UnitTest3
{
private delegate void MakeCallbackDelegate(Action<Entity, ServiceError> callback);
[TestMethod]
public void CallbackIntoViewModel()
{
var service = MockRepository.GenerateStub<IMyServiceClient>();
var model = new MyViewModel(service);
service.Stub(s => s.GetData(null)).Do(
new MakeCallbackDelegate(c => model.GetDataCallback(new Entity(), new ServiceError())));
model.GetDataAsync(null);
}
}
public class MyViewModel
{
private readonly IMyServiceClient client;
public MyViewModel(IMyServiceClient client)
{
this.client = client;
}
public virtual void GetDataAsync(Action<Entity, ServiceError> callback)
{
this.client.GetData(callback);
}
internal void GetDataCallback(Entity entity, ServiceError serviceError)
{
}
}
public interface IMyServiceClient
{
void GetData(Action<Entity, ServiceError> callback);
}
public class Entity
{
}
public class ServiceError
{
}
You'll notice a few things:
I made your callback internal. You'll need to use the InternalsVisisbleTo() attribute so your ViewModel assembly exposes internals to your unit tests (I'm not crazy about this, but it happens in rare cases like this).
I use Rhino.Mocks "Do" to execute the callback whenever the GetData is called. It's not using the callback supplied, but this is really more of an integration test. I assume you've got a ViewModel unit test to make sure that the real callback passed in to GetData is executed at the appropriate time.
Obviously, you'll want to create mock/stub Entity and ServiceError objects instead of just new'ing up like I did.