I want to write a java application using swing, spring and hibernate.
I want to use a data binder to populate the gui with the values of a bean, and I also want it to reflect updates of the bean in the gui.
It seems there is a way to do that in spring, using the DataBinder, but as far as I understand you need to implement the property-change code in the beans yourself, and you need to connect the properties of the bean to the setter methods of the gui using strings which I dislike.
I came across this to prevent the manual implementation of the property-change support in the beans:
https://github.com/damnhandy/Handy-Aspects
Now I'm looking for a data binding framework that I can use together with this, which also supports annotations to minimize and ease the configuration of the binder.
I would hope that I can annotate the setters of the gui with an annotation which takes the name of the property - or, even better, if it has the same name like the property, it wires up automatically.
For example, if I have a Person class with properties name and age, I would like to configure the gui like that:
#GUI
public class PersonGui{
[...]
#BoundField
public void setName(String name){
...
}
#BoundField(property="age")
public void setTheAge(int theAge){
...
}
}
Is there anything like this?
I wrote a library that uses spring data binding for Swing using the "same name convention".
Sample code is in https://github.com/chelu/jdal-samples/tree/master/library
Maybe you are interested on trying it.
Related
We are using Spring Cloud Stream as the underlying implementation for event messaging in our microservice-based architecture. We wanted to go a step further and provide an abstraction layer between our services and the Spring Cloud Stream library to allow for dynamic channel subscriptions without too much boilerplate configuration code in the services themselves.
The original idea was as follows:
The messaging-library provides a BaseHandler abstract class which all individual services must implement. All handlers of a specific service would like to the same input channel, though only the one corresponding to the type of the event to handle would be called. This looks as follows:
public abstract class BaseEventHandler<T extends Event> {
#StreamListener
public abstract void handle(T event);
}
Each service offers its own events package, which contains N EventHandlers. There are plain POJOs which must be instantiated programmatically. This would look as follows:
public class ServiceEventHandler extends BaseEventHandler<ImportantServiceEvent> {
#Override
public void handle(ImportantServiceEvent event) {
// todo stuff
}
}
Note that these are simple classes and not Spring beans at this point, with ImportantServiceEvent implementing Event.
Our messaging-library is scanned on start-up as early as possible, and performs handler initialization. To do this, the following steps are done:
We scan all available packages in the classpath which provide some sort of event handling and retrieve all subclasses of BaseEventHandler.
We retrieve the #StreamListener annotation in the hierarchy of the subclass, and change its value to the corresponding input channel for this service.
Since our handlers might need to speak to some other application components (repositories etc.), we use DefaultListableBeanFactory to instantiate our handlers as singleton, as follows:
val bean = beanFactory.createBean(eventHandlerClass, AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
beanFactory.registerSingleton(eventHandlerClass.getSimpleName(), bean);
After this, we ran into several issues.
The Spring Cloud Stream #StreamListener annotation cannot be inherited as it is a method annotation. Despite this, some mechanism seems to be able to find it on the parent (as the StreamListenerAnnotationBeanPostProcessor is registered) and attempts to perform post-processing upon the ServiceEventHandler being initialized. Our assumption is that the Spring Cloud Stream uses something like AnnotationElementUtils.findAllMergedAnnotations().
As a result of this, we thought that we might be able to alter the annotation value of the base class prior to each instantiation of a child class. Due to this, we thought that although our BaseEventHandler would simply get a new value which would then stay constant at the end of this initialization phase, the child classes would be instantiated with the correct channel name at the time of instantiation, since we do not expect to rebind. However, this is not the case and the value of the #StreamListener annotation that is used is always the one on the base.
The question is then: is what we want possible with Spring Cloud Stream? Or is it rather a plain Java problem that we have here (does not seem to be the case)? Did the Spring Cloud Stream team foresee a use case like this, and are we simply doing it completely wrong?
This question was also posted on on the Spring Cloud Stream tracker in case it might help garner a bit more attention.
Since the same people monitor SO and GitHub issues, it's rather pointless to post in both places. Stack Overflow is preferred for questions.
You should be able to subclass the BPP; it specifically has this extension point:
/**
* Extension point, allowing subclasses to customize the {#link StreamListener}
* annotation detected by the postprocessor.
*
* #param originalAnnotation the original annotation
* #param annotatedMethod the method on which the annotation has been found
* #return the postprocessed {#link StreamListener} annotation
*/
protected StreamListener postProcessAnnotation(StreamListener originalAnnotation, Method annotatedMethod) {
return originalAnnotation;
}
Then override the bean definition with yours
#Bean(name = STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME)
public static StreamListenerAnnotationBeanPostProcessor streamListenerAnnotationBeanPostProcessor() {
return new StreamListenerAnnotationBeanPostProcessor();
}
I am trying to create a generic Logger which would be a small standalone code. Different applications can use this Logger for logging.
Let's say, there are two different codebases- CB1 and CB2.
CB1 needs to capture all public methods of all classes under package- CB1/a/b/c
CB2 needs to capture all public methods of all classes under package- CB2/d/e/f
Now, what I have done till now is as below-
A new codebase, say LogUtility which has an Aspect GenericLogger-
public class GenericLogger {
public Object aroundLog(ProceedingJoinPoint jp) {
//logging code goes here
}
}
in some_context.xml-
<aop:config>
<aop:aspect id="loggerAspect" ref="myLogger">
<aop:pointcut id="sample" expression="${logger.pointcutExpr}" />
<aop:around method="aroundLog" pointcut-ref="sample" />
</aop:aspect>
</aop:config>
If CB1 needs to use this LogUtility, CB1 will add LogUtility to its pom/ivy dependency and provide the value of ${logger.pointcutExpr} via a property file at application startup time.
So, it works fine this way for CB1, CB2,...
The only disadvantage of this approach that I think is the long list in the properties file which has the single key i.e.logger.pointcutExpr
Good thing is, whenever any codebase needs to change it can just add a new pointcut in its own properties file. So a single Aspect can serve multiple codebases.
Earlier, I was trying to do something like this,
#Aspect
#Component
public class GenericLogger {
#Around(<can't make this dynamic>)
public object aroundLog(ProceedingJoinPoint jp) {
//logging code goes here
}
}
The problem with the above is that values passed to any annotation must be final, so can't go with this approach.
I was wondering if there is anything that can be done to achieve this on the fly.
1. Any way in which different codebases can provide the value of the key logger.pointcutExpr without explicitly creating a properties file.
2. Or is it possible to register pointcut with an Aspect on the fly?
I've been googling a lot on this and I'm finding basic AOP tutorials everywhere. I think to do something like this I need to dig deeper in AspectJ along with Spring AOP. I found below links-
https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/aop.html#aop-choosing
how to apply spring aop for legacy code by taking pointcut as input from user
https://eclipse.org/aspectj/doc/next/devguide/ltw-configuration.html
I have basic knowledge of AspectJ, what I'm looking for could be silly.
You can make what is in the Around method dynamic (sort of) by using a static final expression.
But I would suggest something else.
You can definitely do this sort of thing in AspectJ, it's just that you will need to firstly think of the Aspect as describing what expression will execute for the super set of all your cases. Then within the aspect define the behaviour you are wanting to achieve. So for instance you can use Object target = joinPoint.getTarget(); to get the target (class which was executing the method), and then use String canonicalName = taget.getCanonicalName() which will include the package in the name, and then you can do stuff like:
if(getCanonicalName.contains("some/package") {
System.out.println("You can do better than this if statement");
}
And make whatever if statements you need to differentiate between the various packages which are contained in the canonical name. That way you can have greater control over what happens for each package.
i have a few different aspects in my application and i want them to be able to communicate. is it possible to somehow access one from another or the only way is to have some static field serving as a 'message board'?
i'm talking about aspectj, NOT spring aop. also i'm using the .aj files so i'm not limited by the annotation-only syntax
Edit:
To provide sample use case and the code i'm thinking about: Let's say i want to have different aspects guarding my banking app against frauds. And i want them to communicate sometimes to decide together how to react on new types of timeseries and together change the fraud detection policy:
public aspect MyAspect1 {
private MyState myState = ...
pointcut myPointcut(): ...
before(): myPointcut {
MyAspect2 other = ... // how to get the reference to another similar aspect?
}
}
I have a (web-)application that needs special configurations and/or extensions based on the customer using the application. I call these additions "plugins" and they are auto discovered by classpath scanning when the application starts. For extensions that is incredibly easy. Let's say I want to have a plugin which adds an API that prints "hello world" when the URL /myplugin/greet is called: I just create a #Controller annotated class with the according #RequestMapping, put this in a myplugin.jar, copy that on the classpath and that's it.
Problems come up when I want to change some defaults and especially if I want to do this multiple times. Let's say my core application has a config like this:
#Configuration
public class CoreConfiguration {
#Bean
public Set<String> availableModules() {
return Collections.singleton("core");
}
}
Now I have two plugins that don't know about each other (but they do know the CoreConfig), but they both want to add themselves to the list of available modules. How would I do that? If I only had a single plugin that wants to override the module list I could override the existing bean from CoreConfiguration, but with two plugins that becomes a problem. What I imagine is something like this:
#Configuration
public class FirstPluginConfiguration {
#Bean
public Set<String> availableModules(Set<String> availableModules) {
Set<String> extendedSet = new HashSet<>(availableModules);
extendedSet.add("FirstPlugin");
return extendedSet;
}
}
Of course a SecondPluginConfiguration would look nearly exactly like this, except that the Set is not extended by "FirstPlugin", but by "SecondPlugin". I tested it to check what would happen and spring will just never call the First/SecondPluginConfiguration "availableModules" methods but it does not show an error either.
Now of course in this case this could easily be solved by using a mutable Set in the CoreConfiguration and then autowiring and extending the set in the other configurations, but for example I also want to be able to add method interceptors to some beans. So for example I might have an interface CrashLogger which has a logCrash(Throwable t) method and in CoreConfiguration a ToFileCrashLogger is created that writes stack traces to files as the name suggests. Now a plugin could say that he also wants to get notified about crashes, for example the plugin wants to ADDITIONALLY send the stacktrace to someone by email. For that matter that plugin could wrap the CrashLogger configured by the CoreConfiguration and fire BOTH. A second plugin could wrap the wrapper again and do something totally different with the stacktrace and still call both of the other CrashLoggers.
The later does sound somewhat like AOP and if I'd just let ALL my beans be proxied (I did not test that) I could autowire them into my plugin configurations, cast them to org.springframework.aop.framework.Advised and then add advices that manipulate behaviour. However it does seem like a huge overkill to generate proxies for each and everyone of my beans just so that that plugin can potentially add one or two advices one one or two beans.
PUsing Spring 3.2.0.release and JDK 1.6. I've a standalone Java program (NOT running inside tomcat etal) and I'm loading properties from a database.
I've used this excellent article as a base and it works perfectly. Using the PropertiesPrinter bean (defined there) as a base and adding getters I can do stuff like getFileLocation(), getPetDogsName() but then I need to have/create setter/getters for every property.
What I would like to have is a Spring Bean or normal Java class called DatabaseProperties with a method like getProperty("filelocation"); which I can use in my application (main)and so I can retrieve/get the value of the property filelocation which is somewhere inside the information collected by PropertyPlaceholderConfigurer.
I've done a lot of digging but can't seem to find the information I need or at least I'm not able to combine the gathered info into a working program as I'm not fluent with Spring....
Any hint/pointers/urls/code is higly appreciated. It's probably relative easy but it is still out of reach for me atm.
One solution for reading values set by the PropertyPlaceholderConfigurer, is to use the #Value annotation rather than a method for setting class member variables:
class MyClass {
#Value("${file.location}")
private String fileLocation;
...
}