Java configuration and dependency injection (akin to Springs IoC vs. Weld / Guice) - java

Lets say I have a class ListCreator which I want to configure. I want to be able to tell it the sort order and the how to output my table. Therefore I have the boolean sortDescending property and the TableWriter interface which is implemented by PdfTableWriter (but also by XlsTableWriter).
In this example I think configuration and DI go hand in hand. I would like to write something like this Spring (pseudo) example:
<beans>
<bean id="ListCreator" class="ModularListCreator">
<property name="tableWriter">
<ref local="TableWriter"/>
</property>
<property name="sortDescending">
<value>true</value>
</property>
</bean>
<bean id="TableWriter" class="PdfTableWriter"> </bean>
</beans>
Now Spring can do this, but it seems like Weld & Guice can not. Weld for example lets you choose alternatives in the beans.xml, but only for the whole application. What if I want to have one ListCreator for PDFs and another one for XLS at the same time?
I do not get the scope of Weld and Guice at the moment, as they don't seem to allow much of a configuration. The seem to only alleviate the need to write new or to implement your own factories. EJB injection does the same for example, which is nice, but where is the whole configuration part (choosing which instance with what parameters I actually want where).
Coming to the real point: I do not want to use Spring as it seems to be overhead. I much rather use something clean and small at best specified by a JSR. Any suggestions?

Guice actually gives you a lot of power for configuration. Assuming I'm understanding you correctly, here's a simple example of one way you could do this in Guice, using a provider method in a module.
protected void configure() {
bind(TableWriter.class).to(PdfTableWriter.class);
}
#Provides
protected ListCreator provideListCreator(TableWriter tableWriter) {
ModularListCreator result = new ModularListCreator();
result.setTableWriter(tableWriter);
result.setSortDescending(true);
return result;
}
There are other ways too, including making setSortDescending use a binding annotation:
#Inject public void setSortDescending(
#Named("sortDescending") boolean sortDescending)
and then binding that property:
protected void configure() {
bind(TableWriter.class).to(PdfTableWriter.class);
bindConstant().annotatedWith(Names.named("sortDescending")).to(true);
bind(ListCreator.class).to(ModularListCreator.class);
}

For CDI, checkout Seam Solder. It adds the ability to easily configure Managed Beans from an xml file. Judging by the close relationship between the Seam and Weld teams, this mechanism probably has a good chance of making it into a future JSR.

InPUT offers a way if you want a flexible description-based solution. I created the whole example, and added it to the example section.
The code is minimal with:
Design config = new Design("config.xml");
ListCreator creator = config.getValue("ListCreator");
assuming you have a config.xml InPUT design which contains the settings in InPUT syntax:
<SValue id="ListCreator">
<NValue id="SortDescending" value="false"/>
<SValue id="TableWriter" value="Xls"/>
</SValue>
For this to work, you have to define the design space as follows:
<SParam id="ListCreator">
<NParam id="SortDescending" type="boolean" />
<SParam id="TableWriter">
<SChoice id="Xls"/>
<SChoice id="Pdf"/>
</SParam>
</SParam>
You now tailor the programming language independent design space to your Java implementation in a code mapping:
<Mapping id="ListCreator" type="test.ListCreator" constructor="TableWriter SortDescending"/>
<Mapping id="ListCreator.TableWriter" type="test.TableWriter"/>
<Mapping id="ListCreator.TableWriter.Xls" type="test.XlsTableWriter"/>
<Mapping id="ListCreator.TableWriter.Pdf" type="test.PdfTableWriter"/>
From here, extend and customize at free will without touching the code. You mention the case with multiple ListCreator instances. You would have to make 3 changes:
1) design space:
<SValue id="ListCreator" type="[]">
2) design (for example):
<SValue id="ListCreator">
<SValue id="1">
<NValue id="SortDescending" value="true"/>
<SValue id="TableWriter" value="Pdf"/>
</SValue>
<SValue id="2">
<NValue id="SortDescending" value="false"/>
<SValue id="TableWriter" value="Xls"/>
</SValue>
</SValue>
3) Be prepared to receive an array instead (code):
ListCreator[] creators = config.getValue("ListCreator");
You decide the number and alternatives in the descriptor;
the entries arrive in the defined order. This works similar for multiple dimensions (e.g. "[][][]"). You can add alternative table writers with further parameters in the future or change the current parameters without code changes on the caller side. Just make sure the classes are all available, and to test it. There are some sources of error (typos).

Related

How to register or provide pointcuts on the fly to an Aspect

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.

Java annotation execute a method within the annotation declaration(usage for android)

I'm fairly new to the annotation terms.
I have read some sources and came to the conclusion that non answered my question.
Perhaps I googled using the wrong search. Perhaps I overlook, or mayhbe im just clueless..
Anyway here is the deal.
I am busy writing an application that requires "role validation".
To do this I want to use an annotation.
So something along the line of:
#interface Validate (){
}
What I aim to achieve is sometihng along the lines of:
public #interface Validate() {
public Validate() {
//Do validation stuff
return true/false
}
}
So basically I want to define methods within the annotation.
I want to be able to call
#Validate
public void methodThatRequiresAdminRole() {
doStuff();
}
Only admins should be able to enter this method. Otherwise an error should be generated.
so if #validate returns true, the method should be executed
Sorry if I am really unclear. I am not quite sure how to properly ask what I want.
So I hope the examples tell the stories.
Hope to read tips and perhaps even an answer soon.
Thanks.
** EDIT **
I need to stress out the fact that the code must be used on an android application.
So I prefer to not use strange frameworks not meant for android. I have no problem adding a custom library that gives the functionality without any kind of application framework.
Annotations are meta data. What you need to write is an annotation processor. An annotation in itself cannot accomplish the validation logic. The annotation processor will look at the annotations and then do the validation and control the application flow. This SO answer has a good explanation Can Java Annotations help me with this?
You also need to annotate the annotation with #Retention(RetentionPolicy.RUNTIME) so that the annotation information is preserved till the runtime.
#Retention(RetentionPolicy.RUNTIME)
public #interface Validate() {
}
Note, this might be quite off-topic. Using spring AOP with, processing the annotations is fairly straightforward:
Create an aspect:
#Aspect
public class RoleCheckAspect {
#Before("#annotation(your.package.Validate)")
public void doAccessCheck() throws Exception {
// Do validation stuff
if (!valid)
throw new IllegalAccessException("foo");
}
}
}
Set-up your aspect:
In META-INF/aop.xml
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!-- only weave classes in our application-specific packages -->
<include within="your.package..*" />
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.bac.bsl.nonproc.TestAspect" />
</aspects>
</aspectj>
Set-up load time weaving
In the spring context:
<context:load-time-weaver/>
Ensure that the spring-agent is started with your app:
java -javaagent:/path/to/spring-agent.jar -classpath $CP your.package.MyApp
I don't think you can achieve this with annotations alone. They are meant to provide meta information about code elements and not processing logic.
To actually implement the restriction on the annotated methods invocation you will need to check the access by hand inside or outside the method or inject such a check using something like http://www.eclipse.org/aspectj/

Referencing Spring Singletons created in a parent context from a child context

Hard to think of a title for this one! I have a bean that is initialized in a spring container. It loads classes that also create objects from files using Spring classloaders. Some of these objects may have dependencies on expensive objects and I would like those objects to be initialized in the parent. Okay I can't explain in words so on to a simplified example:
public class MainLoader {
public static void main(String[] args) {
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("top-context.xml"));
ChildLoader childLoader = (ChildLoader)beanFactory.getBean("childLoader");
childLoader.loadChildAndDoSomething("message1.xml");
childLoader.loadChildAndDoSomething("message2.xml");
}
}
public class ChildLoader {
public void loadChildAndDoSomething(String childContextfile){
XmlBeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource(childContextfile));
ClassThatDoesStuff classThatDoesStuff = (ClassThatDoesStuff)beanFactory.getBean("classThatDoesStuff");
classThatDoesStuff.saySomething();
}
}
public class ClassThatDoesStuff {
private ReallyExpensiveService reallyExpensiveService;
private String messageStart;
public void saySomething(){
System.out.println(messageStart + reallyExpensiveService.getName());
}
// .. field setters removed for brevity
}
public class ReallyExpensiveService {
public String getName(){
return "Joe";
}
}
These have the following beans in the files:
top-context.xml:
<bean id="childLoader" class="com.mark.test.ChildLoader" />
message1.xml (message2.xml is similar):
<bean id="classThatDoesStuff" class="com.mark.test.ClassThatDoesStuff">
<property name="messageStart" value = "Hello! " />
<property name ="reallyExpensiveService" ref="theExpensiveserviceReference" />
</bean>
<bean id="theExpensiveserviceReference" class="com.mark.test.ReallyExpensiveService" />
When these are run you get the expected:
Hello! Joe
Goodbye! Joe
The only problem here is that the "ReallyExpensiveService" is getting created and cached by Spring on each occasion. This is verified by the log. Better to load up any services that might be needed by the "ClassThatDoesStuff" classes (imagine it's an interface) when the MainLoader is initialzed. I.e. (conceptually) change the spring context files to:
top-context.xml:
<bean id="childLoader" class="com.mark.test.ChildLoader" />
<bean id="theExpensiveserviceReference" class="com.mark.test.ReallyExpensiveService" />
message1/2.xml
<bean id="classThatDoesStuff" class="com.mark.test.ClassThatDoesStuff"
autoWired="byType">
<property name="messageStart" value = "Hello! " />
</bean>
I realise that the way out of this would be to have the ClassThatDoeStuff have a setter for the service and set the value from the Child container which itself had it injected via the main context. But imagine that there are arbitrary services and each of the ClassThatDoesStuff implementers used different ones.. Is there any way for this to work in Spring..?
It seems like the best you can hope for is to instantiate each ReallyExpensiveService one time. (You mention in there that you're not sure which ClassThatDoesStuff may use a different one.) I would probably try to define all of my ReallyExpensiveService beans in the top level context and then hand them out to the classes that use them wherever it's appropriate, either through the XML configuration files that you're using or through some kind of factory that you inject into the ClassThatDoesStuff beans.
You might also try to look for a way to defer the expensive operations of starting up ReallyExpensiveService until you're sure they're going to be used. Of course this depends on what "expensive" means. Is it that the services use too much memory and you don't want them around if they're not in use or that they take too long to instantiate?
In any case, the key here is to have as few instances of expensive things floating around as possible, so you'll want to configure them at the top level so that the references to the single instances can be passed around anywhere.
I fiddled around a lot with this and learnt a lot about spring in the process. I don't think it's possible to get the parent spring context to apply these properties dynamically. I got around the problem by implementing caching in the mainloader object so that expensive types aren't created multiple times frmo the spring definition.
The other possiblity I investigated was making the ChildLoader context aware and allowing the ClassThatDoesStuff to use the parent context to get handles on beans, but this was bedding in spring to the app too much for my liking.

Spring Creates New Objects But Should Not

I'm having the following problem with Spring: I expected that singletons would be created once and then referenced from the Spring cache. But that does not seem to be the case. I have the following lines in my beans.xml:
<bean id="Cache" class="java.util.HashMap" scope="singleton" >
</bean>
which is referenced below like:
<bean id="ManuallyCachingDAO" class="blah"
scope="singleton" init-method="init" destroy-method="destroy">
<property name="cache" ref="Cache"></property>
...
and in the ManuallyCachingDAO the code:
public Object get(int id) {
Object o = cache.get(id);
if (o != null) {
return o;
}
// ... code for retrieving the object from the DB
}
but the HashMap gets emptied in mysterious ways sometimes! That is, I don't think it's actually emptied. I think it's just dropped and created anew when I reference the ManuallyCachingDAO in another class.
Could you tell me how to fix this problem?
EDIT: At Robin's hint: I do the following to get the beans in a lot of classes (not all though):
ClassPathResource blah = etc.;
XmlBeanFactory xbf = new XmlBeanFactory(blah);
...
xbf.getBean("Cache");
... right now I'm doing it (even for a lot of other beans) ... is that a very stupid or very bad idea or both? I think it occurs to me right now what I'm doing wrong... Until now, I just suspected that all XmlBeanFactories were somehow grabbing the same resources which might have been very dumb indeed, or could s/o tell me what's right?
I doubt that Spring is creating new HashMaps. Your configuration looks OK. I am pretty sure something is wrong in your logic.
In the part marked
// ... code for retrieving the object from the DB
do you actually write the retrieved values to the map?
Maybe concurrency is messing up your map. You don't want to use a HashMap as a singleton since it's not thread safe. Try using ConcurrentHashMap instead.
The config looks fine, and Spring is well tested in this respect so I don't think there are going to be any surprises there.
Would you by any chance be creating the Spring context each time you are trying to access the beans? Thereby recreating everything repeatedly.

Using spring to configure application properties

As I already have application.properties, where the database connection settings are defined, I decided it is good to put my application-specific settings in that file too. A step further - as spring reads those properties, I declared my Settings bean as follows
<bean name="settingsBean" class="com.tickets.constants.Settings">
<property name="settings">
<props>
<prop key="backup.dir">${backup.dir}</prop>
<prop key="smtp.host">${smtp.host}</prop>
</props>
<property>
</bean>
Now, it happens sometimes, that I need some of those properties in classes that aren't directly in the spring context. Yes - I can either get the spring context from my web application context, or pass the settings as a method parameter to the utility classes, but here's my alternative approach (this is the Settings class):
private static Properties staticSettings;
#PostConstruct
public void init() {
// making the settings available for static access
staticSettings = settings;
}
Now, this looks a bit wrong. But I can't think of a strong reason for not using it.
So to formulate the question - is there any reason not to use my approach, and is there a better one.
You're right, your solution "feels" wrong - the interaction of statics and instance looks like an anti-pattern, but it's a bit of a slippery one to get a grip on.
My gut feeling would be to push the statics a bit further, and make the class itself more internally-consistent, without sacrificing the Spring integration:
public class Settings {
private static Settings instance;
public static Settings initialise(Properties settings) {
instance = new Settings(settings);
return instance;
}
public static Settings get() {
return instance;
}
private final Properties settings;
private Settings(Properties settings) {
this.settings = settings;
}
public String getProperty(String key) {
return settings.getProperty(key);
}
}
Your Spring config would then use factory-method="initialise" rather than the constructor, and other code can use the static get() method to retrieve the singleton. You avoid duplication of the Properties object, and while the static singleton is a bit of an anti-pattern itself, the code makes rather more sense.
But that's the best I can come up with on a freezing cold Saturday morning :)
This is a good question, and I hope you get several informed and well-reasoned responses (better than the one I expect I'm writing).
The reasons for not using this approach are the same as for adopting the Spring framework in the first place: inversion of control, loose coupling, etc. That said, I feel that if you've considered those points in this context and nevertheless feel that this approach elegantly satisfies your actual needs, go right ahead.
Sometimes I feel that Spring -- indeed many leading frameworks & techniques -- allow themselves to slip into "my way or the highway" API design, where the only way to overcome the limitations of Spring is with more Spring.
It shouldn't be that way. You should be able to adopt a thing like Spring in an existing project without signing up to re-architect every bit of your app.
And in fact there are 365236 ways (yours in one) to share objects between the Spring and non-Spring worlds. There's no technical limitation; but the zealots will give you grief.

Categories

Resources