0

I tried to use @configurable on my project to have @autowired service in object that are outside of spring context or something like that but didn't manage to make it work. The service is always null.

(I compared 4 different tutorials but nothing worked)

So, by despair I tried to download working examples directly to compare them but they didn't worked as well. (but I had to change them a bit, see in "Notes")

Here are the two examples I tried to download but gave me a nullPointerException too :
https://github.com/kenyattaclark/Spring-Configurable-Example
https://www.baeldung.com/spring-inject-bean-into-unmanaged-objects (the link is at the end of the page)

So, are these examples working on your side? Did I miss something really important?

Notes :
I'm using the correto version of java(but I suppose it's unlikely that the problem come from here)

I had to make some changes in the two examples ot make them work so maybe that's why :
for the first one I added a <pluginManagement> in the pom because if I didn't, eclipse was giving me an error "Plugin execution not covered by lifecycle configuration" and if I tried to compile I had the error : "error can't determine superclass of missing type java.lang.Object when batch building BuildConfig[null] #Files=3 AopXmls=#0 [Xlint:cantFindType]"
for the second one I didn't use <pluginManagement>. But I didn't download the parent folder so I changed that in the pom and also forced the java version to 11 or maven was resetting it to 1.5 and had to update the junit test to junit5.

So there is room for me screwing all this up, but I'm tired of looking everywhere on internet and couldn't even get one working example.
So, if someone know what's wrong or how to make one example of @configurable work please tell me.

kriegaex
  • 63,017
  • 15
  • 111
  • 202

1 Answers1

0

I looked at the first example. It uses very old versions of Spring, AspectJ and AspectJ Maven Plugin. I upgraded the POM to use

  • Spring 5.3.16,
  • AspectJ 1.9.9 (supports up to Java 18)
  • AspectJ.dev AspectJ Maven Plugin 1.13.1 (better and more up to date than Mojohaus, also supports Java 18 and can support any more recent version in the future by simply upgrading the aspectjtools plugin dependency, no plugin upgrade necessary).

Please use JDK 11+ on your build system. More recent AspectJ compiler versions need it. You can still compile to Java 8 byte code, though. (But why would you?)

Here is the Maven POM. I also added a separate dependency management section in order to globally manage dependency versions and exclusions. Then I used mvn dependency:analyze and mvn dependency:tree in order to clean up used undeclared and delcared unused dependencies. If your project needs another set of dependencies, you need to adjust it to your needs, of course. I configured it just for what is used in this tiny sample program. In doing so, I also cleaned out a few unused XML name-space and schema declarations. If you need them in your program, just add them again.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.brightdome</groupId>
  <artifactId>spring-configurable-sample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>Spring Configurable Sample</name>
  <description>
    Sample project to show how to work with Spring's @Configurable capability
    to inject dependencies into classes not instantiated by Spring.
  </description>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
    <aspectj.version>1.9.9</aspectj.version>
    <spring.version>5.3.16</spring.version>
  </properties>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
      </plugin>
      <plugin>
        <groupId>dev.aspectj</groupId>
        <artifactId>aspectj-maven-plugin</artifactId>
        <version>1.13.1</version>
        <dependencies>
          <!-- Override older AspectJ compiler in plugin, use latest one -->
          <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>${aspectj.version}</version>
          </dependency>
        </dependencies>
        <executions>
          <execution>
            <goals>
              <goal>compile</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <source>${maven.compiler.source}</source>
          <target>${maven.compiler.target}</target>
          <aspectLibraries>
            <aspectLibrary>
              <groupId>org.springframework</groupId>
              <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
          </aspectLibraries>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
      </dependency>
      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
        <exclusions>
          <!-- Only needed for load-time weaving, not compile-time -->
          <exclusion>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${aspectj.version}</version>
      </dependency>
      <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>${aspectj.version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aspects</artifactId>
    </dependency>
    <!-- Needed by spring-aspects -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
    </dependency>
    <!-- Needed by compile-time aspects during runtime -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
    </dependency>
  </dependencies>

</project>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  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-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
  "
>
  <context:spring-configured/>
  <context:component-scan base-package="com.brightdome"/>
  <context:annotation-config/>
</beans>
package com.brightdome.sample.spring;

import org.springframework.stereotype.Service;

@Service
public class HelloWorldService {
  public void sayHello() {
    System.out.println("Hello world!");
  }
}
package com.brightdome.sample.spring;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;

@Configurable
public class HelloWorldClient {
  @Autowired
  private HelloWorldService service;

  public void sayHello() {
    // Used injected instance of service
    service.sayHello();
  }
}
package com.brightdome.sample.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class HelloWorld {
  public static void main(String[] args) {
    // Initialize Spring Context
    new ClassPathXmlApplicationContext("/META-INF/applicationContext.xml");

    // Instantiate class by new'ing it up. i.e., Do not obtain from Spring context
    HelloWorldClient client = new HelloWorldClient();
    client.sayHello();
  }
}

This compiles and runs just fine in both my IDE (IntelliJ IDEA) and with Maven. On the console, it should simply print "Hello world!" and then exit.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • It worked, at least it doesn't come from my computer or something like that, that's a big relief. Now I can compare it to my project to know what I did wrong. Thx a lot! – whiteRabbit Mar 26 '22 at 12:58
  • It doesn't work anymore on my side. – whiteRabbit Oct 24 '22 at 16:04
  • You accepted my answer 7 months ago, and today you are saying that it does not work anymore. I believe you, but what does that tell you? I suggest to search for the problem in your local development environment. Like I said and like you accepted long ago, it works if you run it exactly the way I showed in my answer. BTW, "It doesn't work anymore" does not qualify as a meaningful problem description. Could you debug anything with that sentence as an imput? – kriegaex Oct 25 '22 at 14:24
  • Yes sorry. I'm glad you saw my comment. Well the error I receive is the classical nullpointer exception on the service I'm trying to use. I absolutely don't know understand why. To summarise I did use your example to make my project work and it did. Recently I tried to launch it again and it wasn't working anymore. I tried it on two different computers, I've updated eclipse and java. And also different things and nothing works anymore. I was thinking that maybe it is indeed a problem with my environment but I'm not so sure anymore. – whiteRabbit Oct 25 '22 at 14:44
  • Maybe it's because of the update of a library or something else? Does your code still work on your side if you try it? I did create a new post with an example I've made using spring boot and spring-starter-poa in maven to be sure to have official library imported by maven here : https://stackoverflow.com/questions/74184130/spring-configurable-nullpointerexception-autowired-service-is-null – whiteRabbit Oct 25 '22 at 14:45
  • Yes, the POM + config + code from my [MCVE](https://stackoverflow.com/help/mcve) in this answer is still working flawlessly. – kriegaex Nov 07 '22 at 08:48