@Value和@Autowired在Azure Functions中无法正常工作。

huangapple go评论81阅读模式
英文:

@Value & @Autowired not working in Azure Functions

问题

我正在Azure Functions中编写一个@TimerTrigger函数。为此,我使用了Azure的Spring Cloud Function。问题是,每次我访问Service或JPARepository时都会得到空指针异常。另外,@Value("${VARIABLE}")返回null,但System.getenv("VARIABLE")确实提供了值。

代码Main.Java如下:

@SpringBootApplication
@EnableJpaRepositories("com.xyz.*")
@ComponentScan(basePackages = "com.xyz.*")
@EntityScan("com.xyz.*")
public class Scheduler {

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

    @Bean
    public void hello() {}
}

函数HelloHandler.java文件如下:

@Component
public class HelloHandler extends AzureSpringBootRequestHandler<Void, Void> {

    @Autowired
    MyService myService;

    @Value("${VARIABLE}")
    private String variable;

    @FunctionName("hello")
    public void execute(@TimerTrigger(name = "timerInfo", schedule = "0 * * * * *") String timerInfo,
                        final ExecutionContext context){
        context.getLogger().info("执行函数..." + variable);    // this gives null.
        context.getLogger().info(System.getenv("VARIABLE"));               // this does provide value.
        myService.hello(context);                                          // null pointer exception here.
        context.getLogger().info("我在这里...");
    }
}

Service MyService.Java如下:

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    private MyRepository myRepository;

    public void hello(ExecutionContext context) {
        List<User> userList = myRepository.findAll();
        for (User user : userList) {
            context.getLogger().info("用户:" + user.getId());
        }

        context.getLogger().info("处理完成。");
    }
}

我正在使用以下依赖项:

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-function-adapter-azure -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-function-adapter-azure</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-function-web -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-function-web</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>

它会抛出以下异常:

Executed 'Functions.hello' (Failed, Id=90714488-b07a-41ac-ae37-d120a1a8e732, Duration=372ms)
System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Failure
Exception: NullPointerException: 
Stack: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	...
Caused by: java.lang.NullPointerException
	at com.xyz.scheduler.HelloHandler.execute(HelloHandler.java:26)
	... 16 more
.

我不明白为什么使用了所有Spring特性后它不能按预期工作。

英文:

I am writing an @TimerTrigger function in Azure Functions. To do so, I used Spring Cloud Function for Azure. The problem is I am getting a null pointer exception every time when I access the Service or JPARepository. Also the @Value("${VARIABLE}") gives null but the System.getenv("VARIABLE") does provide the value.

The code Main.Java is:

@SpringBootApplication
@EnableJpaRepositories(&quot;com.xyz.*&quot;)
@ComponentScan(basePackages = &quot;com.xyz.*&quot;)
@EntityScan(&quot;com.xyz.*&quot;)
public class Scheduler {

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

    @Bean
    public void hello() {}
}

The Function HelloHandler.java File is:

@Component
public class HelloHandler extends AzureSpringBootRequestHandler&lt;Void, Void&gt; {

    @Autowired
    MyService myService;

    @Value(&quot;${VARIABLE}&quot;)
    private String variable;

    @FunctionName(&quot;hello&quot;)
    public void execute(@TimerTrigger(name = &quot;timerInfo&quot;, schedule = &quot;0 * * * * *&quot;) String timerInfo,
                        final ExecutionContext context){
        context.getLogger().info(&quot;Executing the function...&quot;+variable);    // this gives null.
        context.getLogger().info(System.getenv(&quot;VARIABLE&quot;));               // this does provide value.
        myService.hello(context);                                          // null pointer exception here.
        context.getLogger().info(&quot;Here I am...&quot;);
    }
}

Service MyService.Java is:

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    private MyRepository myRepository;

    public void hello(ExecutionContext context) {
        List&lt;User&gt; userList = myRepository.findAll();
        for (User user : userList) {
            context.getLogger().info(&quot;USER: &quot;+user.getId());
        }

        context.getLogger().info(&quot;Process Finished.&quot;);
    }
}

I am using below dependencies:

        &lt;!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-function-adapter-azure --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-function-adapter-azure&lt;/artifactId&gt;
            &lt;version&gt;2.0.1.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;

        &lt;!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-function-web --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
            &lt;artifactId&gt;spring-cloud-starter-function-web&lt;/artifactId&gt;
            &lt;version&gt;2.0.1.RELEASE&lt;/version&gt;
        &lt;/dependency&gt;

It gives exception as:

Executed &#39;Functions.hello&#39; (Failed, Id=90714488-b07a-41ac-ae37-d120a1a8e732, Duration=372ms)
System.Private.CoreLib: Exception while executing function: Functions.hello. System.Private.CoreLib: Result: Failure
Exception: NullPointerException: 
Stack: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.microsoft.azure.functions.worker.broker.JavaMethodInvokeInfo.invoke(JavaMethodInvokeInfo.java:22)
	at com.microsoft.azure.functions.worker.broker.JavaMethodExecutorImpl.execute(JavaMethodExecutorImpl.java:54)
	at com.microsoft.azure.functions.worker.broker.JavaFunctionBroker.invokeMethod(JavaFunctionBroker.java:57)
	at com.microsoft.azure.functions.worker.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:33)
	at com.microsoft.azure.functions.worker.handler.InvocationRequestHandler.execute(InvocationRequestHandler.java:10)
	at com.microsoft.azure.functions.worker.handler.MessageHandler.handle(MessageHandler.java:45)
	at com.microsoft.azure.functions.worker.JavaWorkerClient$StreamingMessagePeer.lambda$onNext$0(JavaWorkerClient.java:92)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
	at com.xyz.scheduler.HelloHandler.execute(HelloHandler.java:26)
	... 16 more
.

I don't understand why it's not working with all the Spring features as expected.

答案1

得分: 1

你需要使用与你的Azure函数同名的bean声明我在同一个Spring Cloud Azure函数应用中使用了带有HttpTrigger和TimerTrigger的Azure函数尝试这样做

HelloHandler.java

public class HelloHandler extends AzureSpringBootRequestHandler<String, String> {

    @FunctionName("hello")
    public void execute(@TimerTrigger(name = "timerInfo", schedule = "0 * * * * *") String timerInfo,
                        final ExecutionContext context){
        context.getLogger().info("执行函数..." + variable);    
        context.getLogger().info(System.getenv("VARIABLE"));               
        super.handleRequest(timerInfo, context);  // 这是正确调用Spring Cloud函数的方式。
        context.getLogger().info("我在这里...");
    }
}



HelloFunction.java

@Configuration
public class HelloFunction {

    @Autowired
    private MyRepository myRepository;
    
    @Autowired
    private ExecutionContext context;
    
    @Bean
    public Function<String, String> hello() {
        return timerInfo -> {
            List<User> userList = myRepository.findAll();
            for (User user : userList) {
                context.getLogger().info("用户:" + user.getId());
            }
            context.getLogger().info("处理完成。");
            return "";
        };
        
    }

}
英文:

You have to declare a bean with the same name with your Azure function. I have my Azure functions with HttpTrigger & TimerTrigger works in the same Spring Cloud Azure function app. Try this

HelloHandler.java

public class HelloHandler extends AzureSpringBootRequestHandler&lt;String, String&gt; {

    @FunctionName(&quot;hello&quot;)
    public void execute(@TimerTrigger(name = &quot;timerInfo&quot;, schedule = &quot;0 * * * * *&quot;) String timerInfo,
                        final ExecutionContext context){
        context.getLogger().info(&quot;Executing the function...&quot;+variable);    
        context.getLogger().info(System.getenv(&quot;VARIABLE&quot;));               
        super.handleRequest(timerInfo, context);  // this is correct way to invoke your Spring Cloud function.
        context.getLogger().info(&quot;Here I am...&quot;);
    }
}

HelloFunction.java

@Configuration
public class HelloFunction {

    @Autowired
    private MyRepository myRepository;
    
    @Autowired
    private ExecutionContext context;
    
    @Bean
    public Function&lt;String, String&gt; hello() {
        return timerInfo -&gt; {
            List&lt;User&gt; userList = myRepository.findAll();
            for (User user : userList) {
                context.getLogger().info(&quot;USER: &quot;+user.getId());
            }
            context.getLogger().info(&quot;Process Finished.&quot;);
            return &quot;&quot;;
        };
        
    }

}

答案2

得分: 0

不确定为什么它不起作用,看起来是正确的。我在演示中尝试了@ValueSystem.getenv(),它们都运行良好。

如果在环境变量中找不到键(VARIABLE),你将会收到以下异常信息
java.lang.IllegalArgumentException: 无法在字符串值"${XXX}"中解析占位符"XXX"。

因此,在您的方法hello()中似乎会得到空指针异常,尝试逐步调试该方法,也许会发生在user.getId()处。

@Value和@Autowired在Azure Functions中无法正常工作。

英文:

Not sure why it does not work, it looks correct. I tried both @Value and System.getenv() in the demo, they worked well.

If you don't find the key(VARIABLE) in your environment variable, you will get this exception
java.lang.IllegalArgumentException: Could not resolve placeholder 'XXX' in string value "${XXX}".

So it seems to get the NullPointerException in your Method hello(), try to debug the method step by step, maybe it will happen at user.getId().

@Value和@Autowired在Azure Functions中无法正常工作。

huangapple
  • 本文由 发表于 2020年9月12日 00:17:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/63850766.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定