AspectJ: List<Object> pointcut args - aop

I have this class:
public class MyClass {
public void updatePeople(List<Person> people) { //DO STUFF }
}
I want to log the size of people when updatePeople is called by AOP.
This is my aspect:
#Aspect
public class MyAspect {
#Pointcut("execution(void com.bla.bla.MyClass.updatePeople(List<Person>)) && args(people)")
public void updatePeople(List<Person> people) {}
#Before("updatePeople(people)")
public void log(List<Person> people) {
log(people.size());
}
}
But log is never called. I guess List<Person> syntax is is not correct in the pointcut. How can I do that?
Thanks.

Solved! I changed the pointcut into this:
#Pointcut("execution(void com.bla.bla.MyClass.updatePeople(..)) && args(people)")
public void updatePeople(List<Person> people) {}

Related

Is this considered as good approach of using interface type in class

Say i have a code as follows
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
class ClassWithInterfaces : Interface1,Interface2
{
void method1(){}
void method2(){}
}
Now in my "manager" class i implement this as follows :
public OtherClass
{
Interface1 interface1;
Interface2 interface2;
public void someMethod()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
interface1 = classWithInterfaces;
interface2 = classWithInterfaces
}
}
I don't feel that this is the right way to do it hovewer i can't come up with other solutions i can't use Dependency Injection Frameworks in my project if you ask about that. Can you tell me wheter apart from DI there is a better way of doing that?
Hello and welcome to Stack Overflow :-)
You don't have to use a framework in order to do DI. In fact, there are some languages that make it impossible to use a framework for DI - e.g., C++.
Any way, in your case, the proper way to do DI is like this:
interface Interface1
{
void method1();
}
interface Interface2
{
void method2();
}
interface Interface3 : Interface1, Interface2
{
void method1();
void method2();
}
class ClassWithInterfaces : Interface3
{
void method1(){}
void method2(){}
}
public OtherClass
{
Interface3 m_interface3;
OtherClass(Interface3 interface3)
{
m_interface3 = interface3;
}
public void someMethod()
{
m_interface3.method1();
m_interface3.method2();
}
}
// And now the usage:
public main()
{
ClassWithInterfaces classWithInterfaces = new ClassWithInterfaces();
OtherClass otherClass = new OtherClass(classWithInterfaces);
}

How to send multiple types of classes into Spring stream source

I upgraded my spring stream from 1.3.0 to 2.1.2 and the default serializer was changed from Kyro (deprecated) into Jackson.
I have a kafka topic that more than one type of messages can be sent to. With Kyro I used to deserialize it into Object.class and then cast it to the relevant type of class.
With jackson I can't achieve this functionality, because I have to specify the type of class I want to deserialize to in advance, otherwise, it's been deserialized into a string.
I tried to find an example but couldn't find anything. Any ideas how can I achieve the same functionality? I want to make it as efficient as possible.
You can add hints to the Jackson encoding so it is decoded to the right concrete type:
#JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="#class")
#SpringBootApplication
#EnableBinding(Processor.class)
public class So56753956Application {
public static void main(String[] args) {
SpringApplication.run(So56753956Application.class, args);
}
#StreamListener(Processor.INPUT)
public void listen(Foo foo) {
System.out.println(foo);
}
#Bean
public ApplicationRunner runner(MessageChannel output) {
return args -> {
output.send(new GenericMessage<>(new Bar("fiz")));
output.send(new GenericMessage<>(new Baz("buz")));
};
}
#JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="#class")
public static abstract class Foo {
private String bar;
public Foo() {
super();
}
public Foo(String bar) {
this.bar = bar;
}
public String getBar() {
return this.bar;
}
public void setBar(String bar) {
this.bar = bar;
}
#Override
public String toString() {
return getClass().getName() + " [bar=" + this.bar + "]";
}
}
public static class Bar extends Foo {
public Bar() {
super();
}
public Bar(String bar) {
super(bar);
}
}
public static class Baz extends Foo {
public Baz() {
super();
}
public Baz(String bar) {
super(bar);
}
}
}
and
com.example.So56753956Application$Bar [bar=fiz]
com.example.So56753956Application$Baz [bar=buz]
See here.
You can still use Kryo if you want. You can just add it manually using #StreamMessageConverter- https://cloud.spring.io/spring-cloud-stream/spring-cloud-stream.html#spring-cloud-stream-overview-user-defined-message-converters.
With regard to "With jackson I can't achieve this functionality, because I have to specify the type of class. . ." - that is not accurate since the type of the class gets picked up from the signature of the handler method and it is transparent to you as a user.

Ninject issue with contextual binding and Lazy<T>

Ninject doesn't seem to correctly use WhenInjectedInto contstraint while also using Lazy<T>. Check the following example. The OnLandAttack and the OnLandAttackLazy should each be using the Samurai instance. But the Lazy<T> version ends up with the SpecialNinja instance. I'm guessing it's because it's not actually initialized in the contructor? But the type should still be correctly registered I would think. Am I missing something? FYI, this is using Ninject 3.2.2 and the Ninject.Extensions.Factory extension 3.2.1
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Load(new WarriorModule());
var amphibious = kernel.Get<IAttack>("amphibious");
amphibious.Execute();
var onLand = kernel.Get<IAttack>("onLand");
onLand.Execute();
var onLandLazy = kernel.Get<IAttack>("onLandLazy");
onLandLazy.Execute();
Console.ReadKey();
}
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
Bind<IWarrior>().To<Samurai>().WhenInjectedInto<OnLandAttack>();
Bind<IWarrior>().To<Samurai>().WhenInjectedInto<OnLandAttackLazy>();
Bind<IWarrior>().To<SpecialNinja>(); // <-- for everything else
Bind<IAttack>().To<AmphibiousAttack>().Named("amphibious");
Bind<IAttack>().To<OnLandAttack>().Named("onLand");
Bind<IAttack>().To<OnLandAttackLazy>().Named("onLandLazy");
}
}
public interface IWarrior
{
void Attack();
}
public class Samurai : IWarrior
{
public void Attack()
{
Console.WriteLine("\tSamurai Attack");
}
}
public class SpecialNinja : IWarrior
{
public void Attack()
{
Console.WriteLine("\tSpecial Ninja Attack");
}
}
public interface IAttack
{
void Execute();
}
public class OnLandAttack : IAttack
{
private readonly IWarrior warrior;
public OnLandAttack(IWarrior warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin OnLand attack");
this.warrior.Attack();
}
}
public class OnLandAttackLazy : IAttack
{
private readonly Lazy<IWarrior> warrior;
public OnLandAttackLazy(Lazy<IWarrior> warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin OnLandLazy attack");
this.warrior.Value.Attack();
}
}
public class AmphibiousAttack : IAttack
{
private readonly IWarrior warrior;
public AmphibiousAttack(IWarrior warrior)
{
this.warrior = warrior;
}
public void Execute()
{
Console.WriteLine("Begin Amphibious attack");
this.warrior.Attack();
}
}

Constructor parameter for injected class

Let's say I would like to inject an implementation of this interface:
interface IService { ... }
implemented as:
class MyService : IService
{
public MyService(string s) { }
}
in an instance of this class:
class Target
{
[Inject]
public IService { private get; set; }
}
I do the injection by calling kernel.Inject(new Target()), but what if I would like to specify the parameter s of the constructor depending on some context when calling Inject?
Is there a way to achieve such context-dependant service initialization at injection?
Thanks!
In most cases you should not use Field Injection, it should be
used only in rare cases of circular dependencies.
You should only use the kernel once at the start of your
application and never again.
Example Code:
interface IService { ... }
class Service : IService
{
public Service(string s) { ... }
}
interface ITarget { ... }
class Target : ITarget
{
private IService _service;
public Target(IServiceFactory serviceFactory, string s)
{
_service = serviceFactory.Create(s);
}
}
interface ITargetFactory
{
ITarget Create(string s);
}
interface IServiceFactory
{
IService Create(string s);
}
class NinjectBindModule : NinjectModule
{
public NinjectBindModule()
{
Bind<ITarget>().To<Target>();
Bind<IService>().To<Service>();
Bind<ITargetFactory>().ToFactory().InSingletonScope();
Bind<IServiceFactory>().ToFactory().InSingletonScope();
}
}
Usage:
public class Program
{
public static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new NinjectBindModule());
var targetFactory = kernel.Get<ITargetFactory>();
var target = targetFactory.Create("myString");
target.DoStuff();
}
}
Simply done using parameters...
kernel.Inject(new Target(), new ConstructorArgument("s", "someString", true));

Overriding FluentNHibernate DefaultCascade for many types at once

I have an abstract entity base class defined like this:
public abstract class SessionItem : Entity
{
public virtual Session Session { get; set; }
}
In addition, I'm using auto mapping:
private AutoPersistenceModel CreateAutomappings()
{
return AutoMap
// configuration
.Conventions.Add(DefaultCascade.All())
// more configuration
}
SessionItem has several derived classes/tables, and I'd like to override the cascading policy for all of them. I tried the following:
public class SessionItemAutommapingOverride : IAutoMappingOverride<SessionItem>
{
public void Override(AutoMapping<SessionItem> mapping)
{
mapping.References(x => x.Session).Cascade.None();
}
}
But unfortunately the override is not called since SessionItem is abstract (and is not mapped). I prefer to avoid overriding it for each subclass (using IAutoMappingOverride).
Is there any way to override cascading for multiple types, without using IAutoMappingOverride<> for each one?
public class SessionReferenceCascadeNone : IReferenceConvention, IReferenceConventionAcceptance
{
public void Accept(IAcceptanceCriteria<IManyToOneInspector> criteria)
{
criteria.Expect(x =>
typeof(SessionItem).IsAssignableFrom(x.EntityType) &&
x.Property.PropertyType == typeof(Session));
}
public void Apply(IManyToOneInstance instance)
{
instance.Cascade.None();
}
}
Apparently this is possible by using IReferenceConvention:
public class CascadeNoneOverrideConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
// override
}
}