Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring: confusion over the right learning path

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.

like image 837
Neil Walker Avatar asked Jan 16 '17 17:01

Neil Walker


People also ask

Is learning spring worth it in 2022?

Spring Boot is one of the best frameworks for Java developers and if you don't know yet, probably 2022 is the best time to learn Spring Boot.

What is the learning path for Spring Boot?

The framework's core features can be used by any Java application and are ideal for enterprise and web app development. Learn how to get started with Spring using Spring Boot to build dynamic, data-driven applications. This path requires basic fluency in Java, covered in our Become a Java Programmer learning path.

How long it will take to learn Spring?

To learn Spring Framework Basics like Dependency Injection, Bean Life Cycle, Autowiring, MVC, AOP(Aspect Oriented Programming), it should take around 50+ Hrs, assuming spending about 2 to 3 hrs, in about 30 days(approximately) & it also depends on your prior expertise/experience, you will get some confidence.

Can I learn Spring Boot in one week?

You can learn Spring Framework in around 4 weeks and during the 4 weeks time you can learn it from beginning. In Spring framework you have to start with the SpringCore, SpringAOP and then learn the web development using Spring Web. After this you should learn the advanced concepts of the Spring Framework.


2 Answers

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.

like image 125
M. Deinum Avatar answered Nov 16 '22 02:11

M. Deinum


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

like image 36
Alexandru Hodis Avatar answered Nov 16 '22 01:11

Alexandru Hodis