Here are the questions resulted from reading the Spring Reference, please help.
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
(2) We have the following config instructions:
<context:annotation-config/>
<context:component-scan base-package=".."/>
<mvc:annotation-driven/>
Do these instructions duplicate theirselfs? In which cases yes, in which no?
(3) I am a bit stuck with all that ways Spring introduces to convert from string to object: PropertyEditor, Conversions, Formatting..
Here is a simple use case:
I have a Spring MVC controller that processes some POST request. That request is a result of filling some form. The form is a web representation of some entity.
So, given a the user submits a new Project form. In that form exist a date field and a manager's name field to be selected from the list of existing managers. The entered date should be converted to Date property of Project object, and manager's name - to Manager property, created or located by this name (i.e. I want to inject Manager into his Project). What should I use in this case? Property editors, formatters, something else?
(4) Generally, may I say that all the #interface classes that are found on classpath can be used by Spring as annotations?
In other words, how can I know which annotations can be used in my project? All that can be found in my classpath, or I need to register them somehow?
(5) I tried to use spring aop without aspectj.jar: just created an Aspect and addred XML definition for this aspect (without any annotations). As a result it throws "class not found Exception: org/aspectj/weaver/BCException".
So looks like I cannot use Spring AOP without aspectJ library?
(1) Do I ever need manual creation of ApplicationContext? Do I ever need second instance of AplicationContext?
Spring is typically usd in two environments - in web development and in desktop applications/standalone servers. In the former case the ApplicationContext is created automatically via ContextLoaderListener defined in web.xml or WebContextInitializer in Servlet 3.0 container.
In the latter case (standalone application) you are responsible for creating and destroying the application context.
(2) We have the following config instructions:
<context:component-scan base-package=".."/> provides all the functionality of <context:annotation-config/> plus (surprise!) component scanning. <mvc:annotation-driven/> is completely independent and it recognizes spring-mvc annotations like #Controller.
[...]The entered date should be converted to Date property of Project object[...]
Register custom editor within #Controller:
#Controller
public class FooController {
#InitBinder
public void binder(WebDataBinder binder) {
binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
public void setAsText(String value) {
try {
setValue(new SimpleDateFormat("yy-MM-dd HH:mm:ss").parse(value));
} catch (ParseException e) {
setValue(null);
}
}
});
}
}
[...]how can I know which annotations can be used in my project?[...]
I found this awesome annotations support sheet some time ago (I am not an author). It will tell you which annotations are enabled when.
All that can be found in my classpath
#Inject is enabled if it is found on the CLASSPATH, other annotations need to be enabled manually, see above.
So looks like I cannot use Spring AOP without aspectJ library?
You can use Spring without CGLIB if you only use interface proxies (i.e. you only apply aspects on classes implementing at least one interface). Otherwise you need CGLIB to dynamically create subclasses.
Related
I have a spring-boot project. Some of the classes I am using it in the 'spring' way, meaning that they are annotated by "#Service", "#Repository", "#Autowired". At the same time, I have lots of classes, which are only used in the normal Java way, meaning that there are no any Spring annotations, and they are created in the standard way of constructing an object in a constructor.
For example, one of the non-annotated classes is:
public class GenericTree<T>
{
private GenericTreeNode<T> root;
public GenericTree ()
{
root = null;
}
public GenericTreeNode<T> getRoot ()
{
return this.root;
}
public void setRoot (GenericTreeNode<T> root)
{
this.root = root;
}
...
}
Is it OK or normal to have a mixure of classes with or without Spring annotations? Probably, I could convert all non-annotated classes into annotated classes by using Spring's annotation markers. Does that really benefit or is it necessary?
BTW, my application's main logic and functions are not web-centric, although they are created as a Spring project. The reason I created in Spring is I want to provide a restful service for my interface so that I can easily test in browser in development, and others can use it with Restful service.
Yes it is ok.
Keep in mind that annotations are not Spring exclusive. Annotations were introduced in Java 5 and they are just meta data for your Java code. This meta data can be useful at:
Compile time
Build time
Runtime
You can even create your own custom annotations and annotate your code with them.
Spring framework comes with some annotations and each one of them has its purpose, but that doesn't mean you have to annotate all your classes with Spring annotations when you are using this framework.
When you annotate your classes as Spring Beans, they become part of the Spring Application Context, thus making them available to be injected with the #Autowired annotation (Spring framework is based on the dependency injection design pattern). But Spring annotations have other implications too, I cannot go into the detail of each one of them but for example, you have to consider that the default scope of annotations like #Bean, #Component, #Controller, #Repository, #Service is Singleton. So whenever you annotate a class with one of these annotations and you don't define a scope, what you get is a singleton class shared all over your application. Other scopes are:
singleton
prototype
request
session
application
websocket
Taking in consideration your GenericTree class, does it make sense to annotate an abstract data structure class as a Spring Bean? Probably not.
So yes, when you develop an application based on Spring framework the normal thing is to have a mixture of Spring annotated classes and regular POJO's.
I recommend you to read the Spring framework documentation, learn what dependency injection is and the purpose and implications of the most used Spring annotations.
The past few days I've been teaching myself Spring Boot and created a REST web service server and client, then added basic authentication and deployed as a standalone and a war package. I did this through incorporating spring-boot-starter-web, spring-boot-starter-test, spring-boot-starter, spring-boot-starter-security, spring-boot-starter-tomcat, spring-web, jackson-databind in my gradle project and copying hten modifying via various websites.
After getting confused by the multitude of websites doing things in completely different ways (completely different annotations, some use of configuration files) it worked and I then modified it using an interceptor/message converter, raw headers and then through a rest template builder.
However, I feel like I really have no idea how or why it worked, even though I wrote a fair bit of code to get it all working, including Basic authentication, in 4 different ways. It just magically worked, and I don't like it: for example, if I wanted to add more stuff that wasn't 'boot' based, how would I do it, or what are all the annotations doing and why are they required, e.g. #SpringBootApplication, #Configuration, or why are some classes #Bean and others not).
To cut a long story short, spring is a massive framework (the website listing the packages takes over a page by itself), should I really be learning spring core/framework before anything else, then maybe spring MVC or spring web services before learning boot?
I can find many resources on teaching me the various packages, but none that tells me why they work or where to really start and specifically nothing will tell me how the packages interlink. It's quite overwhelming.
I expect this will get closed down as not constructive, but it seemed to be the best place to get an answer on Spring.
A very short history of Spring
Lets start with a little history lesson... The year is 2002 and most Java developers have been laboring in the J2EE space and a lot of them were not happy. One of them was Rod Johnson who wrote a book called Expert One-on-One J2EE Design and Development and it was how one could develop enterprise application without EJBs and in a better fashion. The code for this book became the foundation of the Spring Framework.
Spring Configuration
Lets take a look at a simple Java class.
#Component("hello")
public class HelloWorld {
private String name = "World!";
public void setName(String name) {
this.name=name;
}
public void sayHello() {
System.out.println("Hello, " + name);
}
}
Spring Configuration - Property Files
In the beginning the only configuration option was to use a properties file. Lets name this file application-context.properties. To create an instance of the java class above and set a name, the following content in the application-context.properties was needed.
hello.(class)=biz.deinum.samples.configurations.HelloWorld
hello.name=Marten!
The (class) was a special property (there are more like (scope) and (abstract) see the javadoc for more options. This would indicate which class was needed to be loaded. To use the properties file one would have to create a PropertiesBeanDefinitionReader pass that a BeanFactory. (Which in turn can be passed to an ApplicationContext if you need fancy features like AOP)
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:application-context.properties");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();
However that property based configuration was a bit limiting and XML was concurring the world. Hence the first steps into XML configuration where born.
Spring Configuration - XML Files (part 1)
To represent the same configuration with XML the following would be needed.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="biz.deinum.samples.configurations.HelloWorld">
<property name="name" value="Marten!" />
</bean>
</beans>
When loaded this would create an instance of HelloWorld with the same settings as the property file. Loading it would require an XmlBeanDefinitionReader.
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("classpath:/applicationContext-basic.xml");
HelloWorld helloWorld = beanFactory.getBean("hello", HelloWorld.class);
helloWorld.sayHello();
Spring Configuration - XML Files (part 2)
XML is quite verbose but readable. But configuring things like AOP (Transactions for instance),MVC etc. are quite labor some. (Or things like security see this for the predecessor of Spring Security without a namespace). So the new and improved XML had the notion of namespaces allowing things like <tx:annotation-driven /> <aop:config /> etc.
Spring Configuration - Annotation Driven
The next step was the introduction of Java5, which allowed annotations. As the whole Java community asked for annotation based configuration this was added. Hence the introduction of #Component, #Autowired and the likes.
Adding #Component to the HelloWorld class and use the namespace to enable component scanning reduces the amount of XML one has to write.
Assuming #Component("hello") is on the HelloWorld class the following XML is needed.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="biz.deinum.samples.configurations" />
</beans>
To load this configuration the just change the location of the file to load.
Spring Configuration - Java Config
Then all of a sudden the love for XML was over and people wanted to use a language they know and that language is Java. Hence the birth of Java Based configuration.
#Configuration
public class HelloWorldConfiguration {
#Bean
public HelloWorld hello() {
HelloWorld helloWorld = new HelloWorld();
helloWorld.setName("Marten!");
return helloWorld;
}
}
The #Bean annotation is an indication that this method produces a bean and is processed using ASM before being actually loaded by Spring. However Java Config processing is quite complex and works only with an ApplicationContext. You can either add the #Configuration class to an xml file and load that to have it processed or use a specialized AnnotationConfigApplicationContext to load (or detect) it.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
context.getBean("hello", HelloWorld.class).sayHello();
In XML we have namespaces for making configuration easier. In Java Config land we have the various #Enable* annotations like #EnableTransactionManagement which is the same as <tx:annotation-driven /> in XML.
Thoughts / Suggestions
Which configuration option to use, if you are new I suggest start with Java based configuration, although XML is probably a bit easier to understand (IMHO). All configuration options still work today, you can even mix and match them if need arises.
For Spring it doesn't matter, what matters for Spring are the BeanDefinitions which source is used to construct them (properties, xml or java configuration) doesn't matter.
Spring Boot
Thus far the only thing covered is Spring itself. No other project has been touched (although have been mentioned). But as you can imagine time goes on and as configurations and application complexity grew we wanted more convention over configuration. One of the reasons Spring Boot has seen the light.
Marking a class with #SpringBootApplication makes that class a #Configuration, will enable component-scanning (starting from the same package the annotated class is in) and will enable auto configuration.
#SpringBootApplication
public class HelloApplication {
public static void main(String[] args) {
ApplicationContext context = SpringApplication.run(HelloApplication.class, args);
BeanFactoryHelper.sayHello(context);
BeanFactoryHelper.statistics(context);
}
#Bean
public HelloWorld hello() {
HelloWorld hello = new HelloWorld();
hello.setName("Marten!");
return hello;
}
}
This class will launch the application, say hello, print some info on the context and end. Without you creating an application context or factory yourself.
Why the #Bean method well the HelloWorld class is in a package not covered by the default component scanning of Spring Boot and hence we need to declare the bean. We can do this in the HelloApplication class because that is also an #Configuration (due to that being a meta annotation on #SpringBootApplication).
Now if you replace #SpringBootApplication with #SpringBootApplication(scanBasePackageClasses = HelloWorld.class) you could remove the #Bean annotation as the HelloWorld would now be detected by component scanning (enabled by the #ComponentScan meta annotation on #SpringBootApplication).
The code for this answer can be found here.
Spring framework it's about dependency injection and it's used for REST web services, but that doesn't mean you can't have Spring in any basic application.
To cut a long story short, spring is a massive framework (the website listing the packages takes over a page by itself), should I really be learning spring core/framework before anything else, then maybe spring MVC or spring web services before learning boot?
You should learn how spring works in general and how does instantiations work. Basically it does a search in your project and instantiate every class annotated with #Component (#Service, #RestController, #Controller ... and so on). When you #Autowire, a reference is passed to your variable.
After getting confused by the multitude of websites doing things in completely different ways (completely different annotations, some use of configuration files) it worked and I then modified it using an interceptor/message converter, raw headers and then through a rest template builder.
Most of the examples that you can find on the internet older than 1-2 years are probably outdated(but not always). When you search for something keep this in mind. This is the main cause why there are so many implementations.
I can find many resources on teaching me the various packages, but none that tells me why they work or where to really start and specifically nothing will tell me how the packages interlink. It's quite overwhelming.
It is overwhelming. It is a big framework with a large domain of applicability. Best place to learn how things work is: https://spring.io/docs/reference
Although I have worked in Spring framework for a while, I believe I still don't fully understand it. I want to know how and where dependency injection works.
To reinforce the concepts, I created a standalone Java program, and wanted to see how to inject the implementation using Spring framework.
Here is the snippet of spring bean file:
<beans .....>
<bean id="CommomImpl" class="com.example.common.impl.CommomImpl">
</bean>
<bean id="SimpleImpl" class="com.example.simple.impl.SimpleImpl">
</bean>
</beans>
Now, the below is the standalone Java program where I wanted to see how DI works.
public class MainApp {
Resource(name = "SimpleImpl") -------------------> (1)
static SimpleTasks simpleTasks1;
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-bean-config.xml");
SimpleTasks simpleTasks = null;
CommonTasks commonTasks = null;
simpleTasks = (SimpleTasks) context.getBean("SimpleImpl"); ----->(2)
simpleTasks.print("USER");
commonTasks = (CommonTasks) context.getBean("CommomImpl"); ----->(3)
commonTasks.add(3,3);
simpleTasks1.print("USER"); ---------(4)
}
}
With regards to above program, I have following questions:
Q1: The code at (1) doesn't provide any injection, that is simpleTasks1 is null. What this is so? How come in web-applications, we can inject implementation using similar fashion?
Q2: Are (2) and (3) dependency injection?
Q3: The code at (4) gives null pointer exception, because (1) doesn't inject the implementation. It is this which is confusing me. Under what situations does DI work? When we create the web-application, we deploy the .war inside a web-container and NOT in Spring container, then how come #Resouce(name = "xyz") works, when the spring framework jars itself are provided as dependency to the application.
Any detailed explanation would be of great help to clear these doubts.
Dependency injection works by having a way (configuration) to provide dependencies in your classes. Instead of having the class create its dependencies, you pass the required objects from outside. This makes your code testable and you can take advantage of object reusability.
Dependency injection in Spring works in a similar way with other DI frameworks.
You can either inject a dependency of a class through its constructor, or through a member field (private fields also work in Spring).
What you're doing is calling the spring context to locate the dependency. Once you do this, Spring will try to locate a bean (provider) for the dependency you want. Once it finds it, it will create the object (by resolving its own dependencies as well) or use an existing instance of it and it will return the instance to you.
Spring provides the #Autowired annotation, as a replacement of using the context, which you can use to inject dependencies in your classes and it makes your code cleaner and safer since you don't use the bean name to inject you dependency.
You could also have a look at Java based configurations for spring to avoid configuring your beans in XML files and use the #Bean annotation.
I would strongly suggest to have a look at the guides in the Spring website, especially the ones that use Spring Boot since they are giving you all the info you need to setup a basic example using Java annotations.
This question already has answers here:
Why is my Spring #Autowired field null?
(21 answers)
Closed 7 years ago.
In order to provide POJOs in my legacy web app (Tomcat 8.0.26) with the ability to send ActiveMQ messages I've taken the recommendation to introduce Camel (2.15.2) / Spring (4.2.1) into the app to purely for the purpose of managing pooled MQ connections. I'm hoping there isn't an easier way.
Doing things the Spring way I'm thinking everything would need to be based around an MVC architecture with HTTP servlet aware controllers having access to the servlet context and therefore the Spring context in order to inject beanFactory beans into classes annotated with #Controller and #Service (and in fact there must be a Spring #Controller class that enables Spring to inject the #Service class.
However, as I've stated this is legacy code that will not be using the spring web framework.
After much pain it seems that the only way I can get beanFactory beans injected into my POJOs is to go the AspectJ and Weaving route. Before I go down this road can someone tell me that this is currently the best approach (what I've read describing this solution is from 2011 Can't get Spring to inject my dependencies - Spring Newbie) ? Can you point me to documentation and a working example?
Many thanks.
1) aspectj with #Configurable
In your #Configuration annotated class/es
you can add some more annotations
#Configuration
#EnableLoadTimeWeaving(aspectjWeaving = EnableLoadTimeWeaving.AspectJWeaving.ENABLED)
#EnableSpringConfigured
#EnableAspectJAutoProxy
to enable aspectj and the #Configurable annotation,
you need to import the aspectj lib to your project and add the spring tomcat instrumentable java agent in your tomcat lib folder (give a look here, it exaplains how to configure tomcat) http://docs.spring.io/spring-framework/docs/2.5.6/api/org/springframework/instrument/classloading/tomcat/TomcatInstrumentableClassLoader.html
this is not going to help you if you are going to create your pojos using "new"
MyPojo p = new MyPojo(); // no black magic for this, you will need to satisfies the dependencies yourself) but that would be helpful for example when you load some entities through a framework like hibernate and you want to inject something into them.. #Configurable it's an option that can be evaluated in those cases, for what you describe I would rather not use it.
2) You can have some static methods that uses some static set spring-beans and use them from your pojos, something like
class Util{
private static SprintBeanWithJmsSupport x;
public static setSpringBeanToHandleJmsMessages(SprintBeanWithJmsSupport x){
Util.x = x;
}
public static sendJmsMessage(JmsMessage m){
x.sendMessage(m)
}
}
and you can go with Util.sendJmsMessage(...)
this is a bit shitty but it does the work, I don't personally like this approach
3) set your spring beans in your pojo when they need to use them (maybe behind some nice interfaces that suit your domain)
if you go with spring mvc you will likely end up having some controllers that will use some services (generally they handle security / db access and are the entry point to start the "use cases"), as everything wthin these layers is handled by spring it will be very simple to pass the spring-bean to handle jms messaging to your pojos, this seems to me quite a nice way to handle the problem
I went mostly based on memory and something may not be completely accurate, plus my english is .. what it is, so hope this can be helpful anyway.
Right now, I bootstrap Camel using Spring. Using Spring, I can point my Camel contexts to their respective properties files which are then injected at boot time. My issues is that I now want to move my properties from a file to a database, yet still be able to use the property placeholders as I was before. What's the best way to go about doing this?
I've noticed that there's a PropertiesResolver interface that I could implement, but I wouldn't know how to tell Camel about my implementation. Camel's documentation is very lacking in this area.
I also wouldn't be opposed to having Spring get the properties from the database for me, although I don't see that happening.
The PropertiesResolver was designed to help Camel to locate the properties files from OSGi bundle or normal class path.
If you want to setup your owner PropertiesResolver, you can try to use org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer.
You can inject your customer implementation of PropertiesResolver there.
I thought I'd update this with what I found to work. This probably isn't the best method way to do it, but it works and I didn't have to modify the Camel source code. Basically, I converted all of my classes from inheriting from RouteBuilder to inherit from GJKRouteBuilder (which inherits from RouteBuilder). Then in there, I did this:
public class GJKRouteBuilder extends RouteBuilder {
#Override
protected void checkInitialized() throws Exception {
//Get properties from CamelContext using getContext()
//Lookup properties from DB based on CamelContext
//Get the properties component from the context (or create one)
//call setOverrideProperties() on properties component
super.checkInitialized();
}
}
Again, probably not the best method, but it works. Now, any route that inherits from GJKRouteBuilder and has the proper values wired up through Spring will have the properties injected into the properties component as if they were coming right from a properties file.