0

When using Spring DI via "@Autowired" gives NPE and as per comments if I tried giving "@Component" to TestLogger but gives "Consider defining a bean of type 'java.lang.String' in your configuration."

Project LogTester

@SpringBootApplication
public class TestSpringBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(TestSpringBootApplication.class, args);
        System.out.println("TestSpringBootApplication !! ");        
    }
}
public class TestLogger {

    private static final String KEY_VALUE_DELIMITER = "=";
    private static final String KEY_VALUE_PAIR_SEPARATOR = ", ";
    private static final String DOUBLE_QUOTES = "\"";
    private static final String ESCAPED_DOUBLE_QUOTES = "\\\\\"";
    private static final String MESSAGE_FIELD_KEY = "message";
    private static final String THROWABLE_CLASS_FIELD_KEY = "throwableClassName";
    private static final String THROWABLE_MESSAGE_FIELD_KEY = "throwableMessage";
    private static final String STACK_TRACE_FIELD_KEY = "stackTrace";
    private static final String STACK_TRACE_ELEMENT_SEPARATOR = ",";
    
    private final Map<String,Object> _fieldsMap = new LinkedHashMap<>();
    
    public TestLogger withField(String key, Object value) {
        _fieldsMap.put(key, value);
        return this;
    }
    
    private TestLogger(String message) {
        withField(MESSAGE_FIELD_KEY, message);
    }
       @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            boolean firstIteration = true;
            for (Map.Entry<String, Object> field : _fieldsMap.entrySet()) {
                String key = field.getKey();
                String value;
               
                    value = Objects.toString(field.getValue(), StringUtils.EMPTY);
                
                // escape all double quotes
                value = StringUtils.replace(value, DOUBLE_QUOTES, ESCAPED_DOUBLE_QUOTES);

                // surround the value in double quotes if it contains a space
                if (value.contains(StringUtils.SPACE)) {
                    value = DOUBLE_QUOTES + value + DOUBLE_QUOTES;
                }

                if (firstIteration) {
                    firstIteration = false;
                } else {
                    sb.append(KEY_VALUE_PAIR_SEPARATOR);
                }
                sb.append(key).append(KEY_VALUE_DELIMITER).append(value);
            }
            return sb.toString();
        }
        

    }

Project B is just one main class to invoke the method of Project A LogTester

@Component
public class MainClass {

    @Autowi
red
    private static TestLogger obj;
    
    public static void main(String[] args) {
        
        System.out.println("HI");
        System.out.println(obj.withField("key", "89899"));
    }
    
}

pom.xml

        <dependency>
            <groupId>com.test</groupId>
            <artifactId>logTester</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies> 

Output is below when Exception in thread "main" java.lang.NullPointerException at test.MainClass.main(MainClass.java:24)

vicky
  • 149
  • 2
  • 7
  • 21
  • 1
    You're creating the instance of `LoggerTest` yourself so Spring doesn't know it should act on the `@Autowire`. Try injecting `LoggerTest` or doing a lookup. Alternatively tell Spring to autowire: https://stackoverflow.com/questions/3813588/how-to-inject-dependencies-into-a-self-instantiated-object-in-spring – Thomas Aug 31 '20 at 11:54
  • and annotate LoggerTest with @Component – Stultuske Aug 31 '20 at 11:55
  • The last question was rightfully closed as dupe, just as this will be. Because your code is the same and you did not follow the suggestion. – luk2302 Aug 31 '20 at 11:55
  • Please start over with a Spring (Boot) tutorial, explaining how injection works. – luk2302 Aug 31 '20 at 11:58
  • @Thomas can you explain what you meant, inject LoggerTest where ? did not get you – vicky Aug 31 '20 at 11:59
  • @luk2302 it last question it was said I should NOT do new() & Autowire at the same time, which I was not doing, can you clarify what is wrong, I am using Autowire is that not correct ? – vicky Aug 31 '20 at 12:01
  • You have an EXACT duplicate of the linked question, it does not get any closer. Read through the linked question, spend some hours trying to understand it, what does `new` do, how does injection work, what does `Autowired` do, etc. – luk2302 Aug 31 '20 at 12:02

1 Answers1

0

In LoggerTest keyLogger is null because it is not injected. Please add the annotation @Component to LoggerTest to enable autowiring and inject LoggerTest via @Autowired to ApplicationRunnerBean (and not via new LoggerTest()).

Milgo
  • 2,617
  • 4
  • 22
  • 37
  • 1
    Both will not work since OP just has `LoggerTest obj = new LoggerTest();` – luk2302 Aug 31 '20 at 11:58
  • Yeah you are right, edited the answer. – Milgo Aug 31 '20 at 11:59
  • @Milgo Edited by removing new(), injecting LoggerTest via Autowired & added component to Loggertest but giving "Description: Field keyLogger in com.test.springboot.LoggerTest required a bean of type 'com.test.springboot.KeyLogger' that could not be found. " – vicky Aug 31 '20 at 12:15
  • @luk2302, have removed object creation part in the code but still not working :( – vicky Aug 31 '20 at 12:16
  • Are your classes TestSpringBootApplication, ApplicationRunnerBean and LoggerTest in the same package? – Milgo Aug 31 '20 at 12:19
  • @Milgo, yes in same package – vicky Aug 31 '20 at 12:21
  • @Milgo also added @SpringBootApplication(scanBasePackages={"com.test.springboot"}) – vicky Aug 31 '20 at 12:27
  • @luk2302, if you could atleast give some input or hint what is that I should correct or look for it would help to think in that lines. – vicky Aug 31 '20 at 12:29
  • 1
    @vicky is `KeyLogger` annotated with `@Component` or something similar? – luk2302 Aug 31 '20 at 12:30
  • Please update your code. It seems like KeyLogger misses @Component. – Milgo Aug 31 '20 at 12:32
  • @luk2302 sorry I had not annotated it, I added "@Component" now but giving "Consider defining a bean of type 'java.lang.String' in your configuration.". I have these in same package and had also added SpringBootApplication(scanBasePackages={"com.test.springboot"}) – vicky Aug 31 '20 at 12:38
  • @Milgo, added that as luk also suggested but giving "Consider defining a bean of type 'java.lang.String' in your configuration.". Have all under same package. – vicky Aug 31 '20 at 12:47
  • Parameter 0 of constructor in com.test.springboot.KeyLogger required a bean of type 'java.lang.String' that could not be found. The injection point has the following annotations: - @org.springframework.beans.factory.annotation.Autowired(required=true) – vicky Aug 31 '20 at 12:49
  • Please update your code. It seems like you are using "@Component" and "@Autowired" at the wrong spots. – Milgo Aug 31 '20 at 13:02
  • @Milgo, I have updated the code and added all that for expert review. Tried giving "@Component" & with out it also but getting error, please suggest. – vicky Sep 01 '20 at 13:02
  • @luk2302, I have updated the code and used Project A that have logger code that I want to invoke from Project B(simple Spring code) with "@Autowired". This gives NPE just as previous one & if I add "@Component", it gives "Consider defining a bean of type 'java.lang.String' in your configuration. " – vicky Sep 01 '20 at 13:04
  • Add @Component to TestLogger. You also have two main methods, you should only use one main classes. – Milgo Sep 01 '20 at 13:04
  • @vicky how is Spring supposed to create a `TestLogger`, what `message` should it pass in? You still seem to not understand what beans are and how spring creates objects, etc. – luk2302 Sep 01 '20 at 13:06
  • @luk2302, sorry if I am not getting the issue, my understanding was "@Autowired" will ask Spring to create and manage the object of class TestLogger, using which I can invoke its method ? Please correct – vicky Sep 01 '20 at 13:09
  • After adding "@Component" to TestLogger Spring will try to create the bean. But it can't because TestLogger needs a String parameter and Spring don't know which value it should use. So you have to omit the String parameter and declare TestLogger as "@Component". Please read about Spring's basics. – Milgo Sep 01 '20 at 13:20
  • @Milgo, 1)as you said if I remove parameterised String constructor Project A complies with "@Component" although I could not still understand why, if you could point me to any link about it. 2)Project B still gives NPE "Exception in thread "main" java.lang.NullPointerException at test.MainClass.main(MainClass.java:24)" can you suggest what to change here ? – vicky Sep 01 '20 at 13:32
  • Really want to learn here so breaking my head, by working n practising small codes, I don't think I am able to learn with out codes challenging me. – vicky Sep 01 '20 at 13:35