1

I am kind of a newbie in spring and wondering why my spring (not springboot) program is not working. It is a simple one and that's what is bothering me the most.

I have a main class as follows:

package com.something.main;

@Configuration
@ComponentScan (
        "com.something"
)
public class Main {
    public static void main(String[] args) throws IOException {
       String someValue = SecondClass.secondMethod("someString");
    }
}

SecondClass is defined as follows:

package com.something.somethingElse;

@Component
public class SecondClass {
   @Autowired
   private ObjectMapper om;

    private static ObjectMapper objectMapper;

    @PostConstruct
    public void init(){
       objectMapper = this.om;
    }

    public static String secondMethod(String input){
      String x = objectMapper.<<someOperation>>;
      return x;
    }
}

ObjectMapper is injected in spring ioc as follows:

package com.something.config;
@Configuration
public class ObjectMapperConfig {
    @Bean
    ObjectMapper getObjectMapper(){
        ObjectMapper om = new ObjectMapper();
        return om;
    }
}

Now when I try to run the main method in dubug mode, secondMethod has objectMapper as null always. I am not sure what am i missing here. I don't even see breakpoints in ObjectMapper bean creating method hitting when I try to run the application in debug mode. My understanding is that it would standup the spring IOC on startup and then run the main method. Not happening in my case.

Also, one more thing that I don't know it works is when I create a jar of this application and include it as a dependency in another project. The base project may not have spring or even using spring for that mapper. How would that project that includes this jar as an external dependency be able to call secondMethod in secondClass if springIOC container isn't set up in the consuming application.

Can someone please help me?

Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
Ray S
  • 569
  • 1
  • 8
  • 18

3 Answers3

1

The problem is your Spring context is not getting initialized here, hence SecondClass is not a bean, and hence @PostConstuct does not get invoked ever which results in objectMapper object not getting initialized, hence you would probably get nullpointer exception. You need to initialise spring context.

Change you Main class to something like this:

@Configuration
@ComponentScan (
        "com.something"
)
public class Main {
    public static void main(String[] args) throws IOException {

        // Initialise spring context here, which was missing
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);

 //      SecondClass cls = context.getBean(SecondClass.class);
  //     System.out.println(cls.secondMethod("something"));
       System.out.println(SecondClass.secondMethod("someString"));
    }
}
Ankur
  • 892
  • 6
  • 11
  • @RayS, great happy to help. – Ankur Feb 12 '20 at 04:57
  • Can spring based jars be used in a non spring based java project? Can the jar resulting from the classes mentioned in my post be included as an external project in another non spring java project and static methods be used as is that internally use autowired beans etc? – Ray S Feb 12 '20 at 06:19
  • @RayS, I think it would work because all the spring dependencies would transitively get added to your Non-Spring project's classpath. Although, I guess you would have to initialise Spring context, like I have posted in my ans, from Non-Spring project, and remove/comment the same from Spring App's main method. Having said that, this is something that I believe how it should work. You would probably have to try this. – Ankur Feb 12 '20 at 06:38
1

"SecondClass.secondMethod" is a static method. Execution of this static method doesn't run under Spring Application Context.

You need load Spring Application Context so "@PostConstruct" is triggered and "objectMapper" is assigned.

Here is sample code:

@Configuration
@ComponentScan("com.something")
public class Main {
    public static void main(String[] args) throws IOException {
        ApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
        SecondClass.secondMethod("someString");

    }
}
Kevin Le
  • 266
  • 1
  • 5
  • Execution of static method won't run under spring application context and that is absolutely fine. The way Ray S is making it work with static class is the only possible solution. The problem as you and another person mentioned already is indeed the initialization of spring app context. – Hary Feb 12 '20 at 04:59
-3

Sometime the name of the class that we are defining matches with the another class already defined in some package that we have imported. In this case autowiring won't work. You have created a class ObjectMapper which is already defined in jackson libraries.

  • My class name is ObjectMapperConfig not ObjectMapper. So that won't be an issue. – Ray S Feb 12 '20 at 04:18
  • Ok, problem is you are autowiring variable om but you are using the static variable objectmapper. – Shubham Srivastava Feb 12 '20 at 04:26
  • All that won't be an issue. variable objectMapper is set in postConstruct method and gets assigned with the value of autowired om (objectMapper from spring ioc). I do this because I am in a static method and I can't use a bean from spring ioc directly there. So I created a static variable of the type objectMapper and assigned it's value in postContruct when the bean is created. – Ray S Feb 12 '20 at 04:30
  • @ShubhamSrivastava, this is not the case. Please refer accepted answer here:https://stackoverflow.com/questions/17659875/autowired-and-static-method – Ankur Feb 12 '20 at 04:38