Parametrized BeforeSaveEvent<T> is triggered for every registered listener irrespective of T - spring

I'm trying to generate unique incremented ids for entities. For that purpose I have registered multiple ApplicationListeners for every entity type as:
public class Neo4JCustomerSaveListener implements ApplicationListener<BeforeSaveEvent<Customer>> {
public void onApplicationEvent(BeforeSaveEvent<Customer> event) {
...
}
}
definitions are like:
<!-- Listeners -->
<bean id="customerSaveListener" class="c.b.listener.Neo4JCustomerSaveListener" />
<bean id="employeeSaveListener" class="c.b.listener.Neo4JEmployeeSaveListener" />
<bean id="messageSaveListener" class="c.b.listener.Neo4JMessageSaveListener" />
As seen, BeforeSaveEvent is parametrized with Customer type. But the thing is, when a save event is about to happen for customer, other listeners are also triggered although tese listeners' BeforeSaveEvent is parametrized with different types, such as Employee or Message (while inheriting from the same Entity parent class)
Is this to be expected? And what should be my approach to this problem? First thing coming to mind is to use only one listener and differentiate inside with instanceOf ifs but this seems very ugly.
I'm using neo4j 1.9.M03, spring-data-neo4j 2.1.0.RC4 and spring 3.1.3

Related

Get a message converter bean in Spring boot

I am trying to instantiate a resolver from spring-cloud-aws-messaging, specifically the NotificationMessageArgumentResolver. The problem is that it takes a MessageConvertor as an argument. So, this is what I have so far:
private NotificationMessageArgumentResolver notificationMessageArgumentResolver() {
new NotificationMessageArgumentResolver(this.messageConvertor);
}
To get the messageConvertor, I have tried:
#Autowired
public MvcConfig(MessageConvertor messageConvertor) {}
#Autowired
public MvcConfig(MappingJackson2MessageConverter messageConvertor) {}
but I get the same error either ways no bean found. The documentation is simply asking to use the XML:
<mvc:annotation-driven>
<mvc:argument-resolvers>
<ref bean="notificationResolver" />
</mvc:argument-resolvers>
<aws-messaging:notification-argument-resolver id="notificationResolver" />
Which, according to the doc
registers three argument resolvers: NotificationStatusHandlerMethodArgumentResolver, NotificationMessageHandlerMethodArgumentResolver, and NotificationSubjectHandlerMethodArgumentResolver.
So, following the answer from How to use argument-resolvers using annotation in Spring boot?, I am able to get 2 of the 3 beans added, as they don't need any beans I cannot access, however I am not able to instantiate NotificationMessageArgumentResolver due to the lack of a MessageConvertor. I am expecting all my messages to come purely in JSON, so I do know exactly which MessageConvertor to use, which is the default one for JSON that ships with Spring Boot.
EDIT
The entire file, if anyone is interested: http://pastebin.com/tM471AEv
I wonder if you really need the NotificationMessageArgumentResolver as that is intended to be used when using messaging. As you can see it implements the HandlerMethodArgumentResolver from the org.springframework.messaging package.
I suspect that you want to use the NotificationMessageHandlerMethodArgumentResolver instead. Which is the HandlerMethodArgumentResolver for use with the web instead of messaging. Which is also registered when using <aws-messaging:notification-argument-resolver id="notificationResolver" />
I would also suggest to use the NotificationHandlerMethodArgumentResolverFactoryBean instead of 3 individual beans as that is also the class that is used internally by the namespace and annotation driven configuration.
Your configuration would look something like this.
#Bean
public NotificationHandlerMethodArgumentResolverFactoryBean notificationHandlerMethodArgumentResolverFactoryBean() {
return new NotificationHandlerMethodArgumentResolverFactoryBean();
}
#Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
argumentResolvers.add(notificationHandlerMethodArgumentResolverFactoryBean.getObject());
}

Call certain methods alone in a class using spring/pojo?

I am implementing a health check for my application.I have configured the classes for different logical systems in our application and have written methods which check for conditions across the environment like db count , logging errors , cpu process etc.
Now I have requirement where I have to check only certain conditions ie certain methods in the class according to the host.
What is the best way to access those methods via property file ? Please give your suggestions.
Thanks.
I don't like using reflection for this sort of thing. Its too easy for the property files to be changed and then the system starts generating funky error messages.
I prefer something straightforward like:
controlCheck.properties:
dbCount=true
logger=false
cpuProcess=true
Then the code is sort of like this (not real code):
Properties props = ... read property file
boolean isDbCount = getBoolean(props, "dbCount"); // returns false if prop not found
... repeat for all others ...
CheckUtilities.message("Version " + version); // Be sure status show version of this code.
if (isDbCount) {
CheckUtilities.checkDbCount(); // logs all statuses
}
if (... other properties one by one ...) {
... run the corresponding check ...
}
There are lots of ways to do it but this is simple and pretty much foolproof. All the configuration takes place in one properties file and all the code is in one place and easy for a Java programmer to comment out tests that are not relevant or to add new tests. If you add a new test, it doesn't automatically get run everywhere so you can roll it out on your own schedule and you can add a new test with a simple shell script, if you like that.
If its not running a particular test when you think it should, there's only two things to check:
Is it in the properties file?
Is the version of the code correct?
You can define different beans for every check you need:
<bean id="dbcountBean" class="DBCountHealtCheck" scope="prototype">
<!-- bean properties -->
</bean>
Then a bean for HealtCheck with operations bean injected:
<bean id="healtChecker" class="HealtChecker" scope="prototype">
<property name="activeChecker"><bean class="PropertiesFactoryBean>
<property name="location">file:path/to/file</property></bean>
</property>
<property name="dbCountCheck" ref="dbCountBean" />
<!-- other properties -->
</bean>
class HealtChecker {
private DBCountHealtCheck dbCountChecker;
private Properties activeChecker;
public void setDbcount(DBCountHealtCheck dbCountChecker) {
this.dbCountChecker = dbCountChecker;
}
public void setActiveChecker(Properties activeChecker) {
this.activeChecker = activeChecker;
}
public void check() {
if("true".equals(this.activeChecker.get("dbCount")) {
this.dbCountChecker.check();
}
}
If with this solution you can't reload file, in HealthChecker remove activeChecker a property public void setPropertiesLocation(URL propertiesLocation); let HealthChecker implements InitializingBean and load properties in afterPropertiesSet()

Spring configuration calling more than one method

I have code which looks like the following:
MyContext context = new MyContext();
context.start();
MyEntity entity = context.getEntity();
I want to inject the MyEntity instance into various classes.
But I don't know how to setup my Spring configuration, where I first create an object, then call a method on it and then finally call another method which returns the entity I want to inject.
EDIT 2 - removed the Strings altogether
The most common type of dependencies injected using Spring don't depend on the user input for their construction. This includes data access objects, services etc.,
You are talking about injecting domain objects whose construction depends on the user input either directly or indirectly.
Spring provides #Configurable annotation to inject such domain objects that are created using new operator. You can search for "#Configurable Domain Driven Design" on the internet to get examples of how this can be implemented. I myself used it in one my applications and wrote a simple post here that might help you get started.
Edit:
To create a bean of type MyEntity as per the specification in your updated question, you would need to
define a bean of type MyContext
Create a MyEntityFactory class that would depend on the MyContext bean.
The factory method would take the MyContext bean as argument, calls context.start() on it and returns an instance of MyEntity.
You would define the MyEntity bean using this factory class.
The MyEntityFactory class would be as follows:
public class MyEntityFactory
{
public static MyEntity getMyEntity(MyContext context)
{
context.start();
return context.getEntity();
}
}
The spring bean configuration will be as follows:
<bean id="myContext" class="FQCN.Of.MyContext" />
<bean id="myEntity" class="FQCN.Of.MyEntityFactory" factory-method="getMyEntity">
<constructor-arg ref="myContext" />
</bean>
Since MyEntity is a singleton bean, the factory method will be called only once, btw.
More on creating beans using factory methods here.

Inject Dynamic Values for the property in Spring

I am very new to Spring and while going through the DI topic through various sources (Book & Internet) I have seen the following pattern of defining bean configuration:
For example we have a class "SampleApp"
public class SampleApp
{
private int intValue;
private float floatValue;
public SampleApp(int value)
{
intValue = value;
}
public void setIntValue(int value)
{
intValue = value;
}
public void setFloatValue(float floatValue)
{
this.floatValue = floatValue;
}
}
Corresponding bean configuration is as follows:
<bean class="somepackage.SampleApp" id="samplebeanapp">
<constructor-arg value="15" />
<property value="0.5" name="floatValue"></property>
</bean>
We have been hard-coding the value here to 15 & 0.5.
Here are my questions :
Is it possible to pass those values as run time parameter with scope as prototype?
If yes, how can we do it? and please elaborate with some example.
Spring configuration files are processed at startup, and Spring singleton beans are instantiated too in that moment. They are not processed again during the application lifecycle, in normal conditions.
You can use such type of property injection to pass configuration values, while you can use injection of object references to determine the structure of your application.
To avoid hardcoding the values inside the XML files, you can extract them in property files using a PropertyPlaceholderConfigurer.
The principle is to program to interfaces as much as possible, so you don't tie yourself to any specific implementation. However, for the case you're thinking, you'll just pass the values at runtime.
Example: BeanA needs the services of DaoBean, but the DaoBean won't be instantiated by BeanA. It will be passed to BeanA through dependency injection and BeanA will only talk to a DaoInterface.
At this point if BeanA want to save 15 and 0.5, will call the methods with the actual values (or more commonly variables).
daoInterface.saveInt(15);
daoInterface.saveFloat(0.5);
I don't use dependency injection to pass the values in this case. Dependency injection is a great tool, but doesn't meant that it has to be used everywhere.

How to bind a bean property to another one and observe changes in Spring Framework

I'm wondering that if there is a way for binding a spring bean's property to another bean's property so if any change on binded property occurs in runtime, what i expect is referencing bean's property also changes. I'll explain more with a little code snippet.
<bean id="johnHome" class="example.Contact">
<property name="phone" value="5551333" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone">
<util:property-path path="johnHome.phone" />
</property>
</bean>
OK. This works at initial bean wiring but what i exactly want is to bind property so if the property changes at runtime the referencing bean also changes. If i should like to show with a metaphor it will seem like this.
<bean id="johnHome" class="example.Contact">
<property name="phone" value="5551333" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone">
<util:bind path="johnHome.phone" />
</property>
</bean>
Am i overloading the spring's concept too much or is this possible without a lot of tricks?
Thanks..
Simplest way - make that property a bean which is referenced by the two other beans, e.g. for a String value have a StringHolder class:
public class StringHolder {
private String value;
// setter and getter elided due to author's lazyness
}
The whole idea behind Spring is (was?) to keep a clean object-oriented design consisting of plain old java objects and use the spring framework to handle the tedious object creation. As for AOP, this should only handle cross-cutting concerns. I'm not at all convinced that this is one of those cases where AOP is a good idea. Your application relies on the behaviour of these phone numbers getting synced to each other, it's one of the main functionalities. As such, your design should reflect this.
Probably the most logical way to handle this specific problem is to make phone numbers their own class (which is also handy if you ever want to distinguish different types of phone numbers).
If you have a PhoneNumber object which takes the number as a constructor argument the mapping becomes trivial:
<bean id="johnFirstPhone" class="example.PhoneNumber">
<constructor-arg value="5551333" />
</bean>
<bean id="johnHome" class="example.Contact">
<property name="phone" ref="johnFirstPhone" />
</bean>
<bean id="johnWork" class="example.Contact">
<property name="phone" ref="johnFirstPhone" />
</bean>
Of course whether you'd map it like this in a static file is another matter, but the thing is in this situation you pretty clearly just need a reference/pointer.
I don't think what you're doing is possible in Spring 2.5. It may be possible in Spring 3, using the new expression syntax, but I don't think so.
Even if it were, it'd be confusing, I think. Better to stick your shared value into its own class and inject an instance of that class into the other beans that need to share it.
I can think of two possibilities.
One is (it is kind of a hack), if you don't have very many beans that need to be linked like the ones in your example, you could inject johnWork into the johnHome bean, and in johnHome.setPhone you could update the johnWork phone property, something like:
public class Contact {
private Contact myWorkContact;
private String phone;
public void setPhone(String phone) {
this.phone = phone;
if (this.myWorkContact != null) {
this.myWorkContact.setPhone(phone);
}
}
public void setWorkContact(Contact c) {
this.myWorkContact = c;
}
}
Or you could have HomeContact and WorkContact both extend a class Contact and do the same injection with that.
If you have tons and tons of beans that will need this (like if your application actually IS dealing with contact information), with AOP (you'll need AspectJ for the example given) I think you could do something like this (it will be a bit memory intensive if you get a ton of objects, but you can see how something like it would work):
Warning: this actually got complicated fast, but I'm pretty sure it would work after you worked out a few kinks
public class Contact {
...
private String phone;
private String name;
private Integer id;
public Contact(Integer id, String name, String phone) {
this.phone = phone;
this.name = name;
this.id = id;
}
public void setPhone(String phone) {
this.phone = phone.
}
//Other getters, setters, etc
...
}
#Aspect
public class ContactPhoneSynchronizer {
//there is probably a more efficient way to keep track of contact objects
//but right now i can't think of one, because for things like a tree, we need to
//be able to identify objects with the same name (John Smith), but that
//have different unique ids, since we only want one of each Contact object
//in this cache.
private List<Contact> contacts = Collections.synchronizedList(new ArrayList<Contact>());
/**
This method will execute every time someone makes a new Contact object.
If it already exists, return it from the cache in this.contacts. Otherwise,
proceed with the object construction and put that object in the cache.
**/
#Around("call(public Contact.new(Integer,String,String)) && args(id,name,phone)")
public Object cacheNewContact(ProceedingJoinPoint joinPoint, Integer id, String name, String phone) {
Contact contact = null;
for (Contact c : contacts) {
if (id.equals(c.getId()) {
contact = c;
break;
}
}
if (contact == null) {
contact = (Contact) joinPoint.proceed();
this.contacts.add(contact);
}
return contact;
}
/**This should execute every time a setPhone() method is executed on
a contact object. The method looks for all Contacts of the same
name in the cache and then sets their phone number to the one being passed
into the original target class.
Because objects are passed by reference until you do a reassociation,
calling c.setPhone on the object in the cache should update the actual
instance of the object in memory, so whoever has that reference will
get the updated information.
**/
#After("execution(example.Contact.setPhone(String) && args(phone)")
public void syncContact(JoinPoint joinPoint, String phone) {
Contact contact = joinPoint.getTarget();
for (Contact c : this.contacts) {
if (c.getName().equals(contact.getName()) {
c.setPhone(phone);
}
}
}
}
Again, there is probably 100 ways you could optimize this, since I'm typing it off the top of my head; that is, if you wanted to go this route in the first place. In theory it should work but I haven't tested it at all.
Anyway, Happy Springing!

Resources