00 Opening Words Stick to Protecting Bom, How to Deal With Spring Layoffs

00 Opening Words Stick to Protecting Bom, How to Deal with Spring Layoffs #

Hello, I’m Fu Jian, and it’s nice to meet you here.

Let me introduce myself first! You might know me, yes, I previously taught a video course on Geek Time called “Netty Source Code Analysis and Practice”. Out of my love for open source, I am a contributor to Netty source code and many other open source projects such as Jedis, Spring Data Redis, influxdb-java, Jenkins, etc. If we have met in the open source community, we are quite destined to meet again.

As for my day job, I am a software engineer working at Cisco China R&D Center. I’ve been in this profession for over ten years. I have also co-authored a book called “Metrics-Driven Development” with my colleagues. During my career, I have worked on various projects, ranging from mobile applications to document storage systems, messaging systems to telephony access systems, and so on. In fact, regardless of the names and levels of these projects, and regardless of the baptism of what level of traffic, you won’t doubt one thing: we heavily use and rely on Spring in our projects.

The Transformation of Spring #

Thinking back, my team and I started using Spring more than 10 years ago, right when I first entered the workforce. At that time, our understanding of Spring began with the SSH framework. Today, Spring has quietly undergone a transformation along with technological advancements.

When Spring wasn’t as widely used as it is today, developing a Java web program was still a challenging task. We had to write a lot of seemingly repetitive code or configurations, and then nervously hope that it would run successfully. However, even with all that repetition, various errors could still occur.

After 2014, the introduction of the convenient and powerful Spring Boot made Spring applications even more widely adopted. It brought great convenience to us Java developers. The first time I saw a Hello World web application written with Spring (the example shown below), I was amazed and that feeling remains vivid in my memory.

@SpringBootApplication
@RestController
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @RequestMapping(path = "/hi")
    public String hi(){
        return "hi, spring";
    };

}

But good news often comes with a double-edged sword. Later on, many people claimed that Spring lowered the technical entry barrier for programmers. It is true that the complex development tasks of the past have become much simpler. However, many people fell into a misconception that simply by wearing a “grid-pattern shirt” and knowing how to “code,” they could become Java developers. Oh, how cruel reality can be!

Journey of Spring Pitfalls #

Whether you are a novice programmer or a seasoned one, as long as you have used Spring, you should have had similar feelings.

Even though you have completed the work, you always feel uncertain. For example, when we add the @RestController annotation to an interface class, sometimes we can’t help but wonder, can we use @Controller instead? Which one is better?

When we encounter a filter that does not execute in the order we want, we usually think of adding @Order immediately, but @Order may not be able to handle all situations. At this time, we may frantically operate and try various annotations, and finally the order may be guaranteed, but each filter is executed multiple times. Of course, it is also possible to really solve the problem, but it is solved in a muddled way.

Moreover, why does something go wrong just because we made a slight change? For example, a common error encountered by beginners is that in Spring Boot, when moving a class in the Controller layer outside the package of the Application, the interfaces provided by the Controller layer will directly become invalid.

And when we encounter problems, where should we start looking for solutions? For example, the following code can run in some projects, but when replaced with another project, it doesn’t work. What’s the situation?

@RequestMapping(path = "/hi", method = RequestMethod.GET)
public String hi(@RequestParam String name){
    return name;
}

Sometimes, it’s not even a matter of changing projects, but adding new features that can cause old features to malfunction. For example, after adding AOP aspect configuration to intercept the login method of the following Bean:

@Service
public class AdminUserService {
    public final User adminUser = new User("fujian");
    public User getAdminUser(){
        return adminUser;
    }    
    public void login(){
        //
    }
}

You may be baffled to find that the following line of code, which originally worked fine elsewhere, suddenly reports a NullPointerException. What’s going on?

At this time, I believe you are at a loss and frustrated. You may even silently curse: “What the hell is Spring doing?”

String adminUserName = adminUserService.adminUser.getUserName();

Why do we have these feelings? The root cause is that Spring is just too “intimate”. It is like a “nanny” that completes all our common tasks. If you are lucky, you may not encounter any problems for a long time.

However, this intimacy is based on many conventional rules. Just like the nanny we hire, she may always assume that you eat Chinese food, so every time you come home from work, the Chinese food is already prepared. But suppose one day you suddenly have the idea of eating Western food, you may only then realize that this intimate nanny only knows how to cook Chinese food, and you can’t eat anything else.

That’s how Spring works. It has many implicit conventions, which may not be the ones you are familiar with. So when you encounter a problem, it’s likely to drive you crazy. On the one hand, we benefit from the ease it brings, because we can work without knowing too much; on the other hand, we may collapse when problems arise and cannot be solved quickly, because we don’t need to and may not even think about knowing more.

At this time, many people jump out and tell you, “You must thoroughly understand Spring in advance!”

But when you browse through the Spring source code, you will definitely feel intimidated. There is really too much, learning without a specific problem is like finding a needle in a haystack. Even if you read most of the best-selling Spring tutorials on the market, you may still feel confused about how much you have mastered. After all, after reading it, you may not be able to foresee what problems you may encounter in the future, and avoiding and handling these problems is often the standard to test your learning achievement.

How I teach this course? #

Tired of running around when encountering problems, it is natural to look for efficient and convenient learning methods. So over the years, I have been organizing various problems encountered in Spring development and classifying them.

When the project is busy, I just make simple records and delve into them when I have time. Now my ToDoList is very detailed, which is also very helpful for my team. For newcomers, this is a comprehensive guide to avoiding pitfalls; for veterans, it is a good memo for problems.

This is the original intention of me doing this course, and I sincerely share it with you here.

In terms of content design, the whole series is organized in a problem-driven manner. The train of thought is as follows:

  1. Present over 50 error cases;
  2. Analyze the causes of the problems from the source code level;
  3. Provide solutions to the problems and summarize the key points.

In addition, most of the problems in this series are not closely related to each other. This is to avoid overwhelming your learning burden. I try to let you understand a problem and its underlying principles in fragmented time as much as possible. In the end, through these numerous problem points, I help you form an overall understanding of Spring and become proficient in it.

In terms of problem selection, I have selected over 50 common problems. These problems mainly come from: problems that my colleagues and I frequently encounter in production environments, high-frequency problems on the Stack Overflow website, and high-frequency problems obtained through common search engines.

The selection of these problems follows these principles:

  1. Not difficult, but common, almost everyone will encounter them;
  2. Not very common, but once encountered, it is easy to fall into a pit;
  3. They can work in certain scenarios but become ineffective in other circumstances.

Course Design #

With the detailed explanation of the specific content, I believe you now have a general understanding of the problems that can be solved in this column. Next, let me tell you about the overall course design to help you further understand.

This column is divided into the following three parts. You can refer to the following diagram to understand my design ideas:

Spring Core Part: Spring Core includes the core functions of bean definition, injection, AOP, etc. It can be said that they are the foundation of Spring. Whether you are doing Spring Web development in the future or using the Spring Cloud technology stack, you cannot avoid these functions. Therefore, here I will focus on introducing common problems in the use of these functions.

Spring Web Part: Most projects use Spring for web development, so I have also organized the unmissable issues in web development, from request URL parsing, header parsing, body conversion to authorization, and more. It is not difficult to see that they cover the entire process from an incoming request to the corresponding response.

Spring Supplementary Part: As a supplement, in this part, I will focus on introducing Spring testing, Spring transaction, Spring Data related issues. Finally, I will systematically summarize the root causes of problems that occur in the use of Spring.

By learning these 50+ common and typical problems, I believe you will have a deeper understanding of the essence of Spring, and you will also be able to see the causes of problems clearly. Ultimately, by mastering the best solutions to these problems, you will be able to apply them to other similar situations.

Tips #

However, there are a few points I still want to remind you about. This course requires a certain foundation. You need to know the basic usage of Spring, such as how to auto-inject a Bean, how to use AOP, etc. Additionally, you also need to have some patience because it involves understanding source code.

Furthermore, this course focuses on practice and filling in the gaps, so in the explanation of each question, it is not possible for me to trace back and present all the background knowledge and the before and after invocation relationships in a complete manner. Otherwise, what you would see is undoubtedly just a Spring tutorial containing a lot of repetitive content, which goes against the original intention of this course.

I hope that when you encounter a question but feel that you lack a foundation, you can promptly review the relevant content. Of course, you can also ask me directly in the comment section, and I will do my best to provide assistance.

Also, there will be many examples and sample codes in the course, as well as some key implementations. I hope you can follow along with my pace to verify them. Only by getting hands-on experience will the impression be profound.

Lastly, I want to say that this column is a repository of questions and also a reference book. Make good use of it. When you encounter various Spring problems again, it will give you confidence! If you have encountered some difficult questions now, feel free to communicate with me in the comment section. For valuable questions that are not covered in the column but deemed important, I will consider delivering them to you in the form of supplementary content later.

Thank you for your trust, see you in the next lesson!