Spring dependency injection not managed beans

I have a JPA domain class that is not managed. It is created using the operator new

.

UserAccount account = new UserAccount();
userRepository.save(account)

      

In my class UserAccount

, I have a method beforeSave()

that depends on my SecurityService

password hash encoding.

My questions are, "How do I get spring DI to inject security into my entity?". It seems that AspectJ and LoadTimeWeaving are what I need. I've tried an array for configs, but I can't seem to get them to work. I always get NullPointerException

when I try to call a method on a nested object.

UserAccount.java (This is a JPA Object)

@Entity
@Repository
@Configurable(autowire = Autowire.BY_TYPE)
public class UserAccount implements Serializable {

    @Transient
    @Autowired
    SecurityService securityService;

    private String passwordHash;

    @Transient
    private String password;

    public UserAccount() {
        super();
    }

    @PrePersist
    public void beforeSave() {
        if (password != null) {
            // NullPointerException Here!!!
            passwordHash = securityService.hashPassword(password);  
        }
    }
}

      

Trying to tell spring to use AspectJ:

NitroApp.java (Main class)

@SpringBootApplication
@EnableTransactionManagement
@EnableSpringConfigured
@PropertySources(value = {@PropertySource("classpath:application.properties")})
public class NitroApp extends SpringBootServletInitializer {


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

}

      

build.gradle (config)

buildscript {
    repositories {
        mavenCentral()
        jcenter()
    }

    dependencies {
        classpath "org.springframework.boot:spring-boot-gradle-plugin:1.2.2.RELEASE"
        classpath "org.springframework:springloaded:1.2.2.RELEASE"
        classpath "org.springframework:spring-aspects:4.1.6.RELEASE"
    }
}

apply plugin: 'java'
apply plugin: 'aspectj'
apply plugin: 'application'
apply plugin: 'idea'
apply plugin: 'spring-boot'

repositories {
    jcenter()
    mavenLocal()
    mavenCentral()
}

mainClassName = 'com.noxgroup.nitro.NitroApp'
applicationName = "Nitro"

idea {
    module {
        inheritOutputDirs = false
        outputDir = file("$buildDir/classes/main/")
    }
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-actuator")
    compile("org.springframework.boot:spring-boot-starter-data-jpa")
    compile("net.sourceforge.nekohtml:nekohtml:1.9.15")
    compile("commons-codec:commons-codec:1.9")
    compile("org.postgresql:postgresql:9.4-1201-jdbc41")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

      

+3


source to share


2 answers


You can inject Spring applicationContext into the class used to start UserAccount.

@Autowired
private ApplicationContext applicationContext;

      

Then create your UserAccount bean like this:



UserAccount userAccount = applicationContext.getBean(UserAccount.class);

      

This way you can inject the required dependencies in the UserAccount class.

+3


source


From your configuration, I am assuming that you somehow expect Spring to manage AOP for you. However, since you are looking @Autowired

for a non-managed bean, you will need to weave yourself either by slicing the load times or by compiling the command. Spring will support default method level parameters.

Since load time over time is related to the use of javaagent as described in 9.8.4 (not always practical in a production scenario), I got ahead of myself and use compile time. The following code and configuration works for me.

Boot configuration

@SpringBootApplication
@EnableSpringConfigured
public class App {
    public static void main(String[] args) {
        System.out.println("Hello World!");

        ApplicationContext ctx = SpringApplication.run(App.class, args);
        Account account = new Account();
        account.testConfigurable();
    }
}

      

Account.java

@Configurable(autowire = Autowire.BY_TYPE, dependencyCheck = true)
public class Account {

    @Autowired
    private SpringService service;

    public void testConfigurable() {
        System.out.println(service.returnHello());
    }
}

      

SpringService.java



@Service
public class SpringService {

    public String returnHello() {
        return "Hello";
    }

}

      

Ugly pom.xml

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <showWeaveInfo>true</showWeaveInfo>
                    <source>1.8</source>
                    <target>1.8</target>
                    <Xlint>ignore</Xlint>
                    <complianceLevel>1.8</complianceLevel>
                    <encoding>UTF-8</encoding>
                    <verbose>false</verbose>
                    <aspectLibraries>
                        <aspectLibrary>
                            <groupId>org.springframework</groupId>
                            <artifactId>spring-aspects</artifactId>
                        </aspectLibrary>
                    </aspectLibraries>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjrt</artifactId>
                        <version>1.8.5</version>
                    </dependency>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <version>1.8.5</version>
                    </dependency>
                </dependencies>
            </plugin>

      

Below are the links I link to.

  • 9.8.1 in Spring doc
  • Maven config from here .

Since I am not an expert in AOP, I am not sure if you are facing the problem of configuring AOP above in the usual way. Discussion here . If you require load times in time, you should go ahead and use that as described in the answer.

+1


source







All Articles