英文:
@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("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() {}
}
The Function HelloHandler.java File is:
@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("Executing the function..."+variable); // this gives null.
context.getLogger().info(System.getenv("VARIABLE")); // this does provide value.
myService.hello(context); // null pointer exception here.
context.getLogger().info("Here I am...");
}
}
Service MyService.Java is:
@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: "+user.getId());
}
context.getLogger().info("Process Finished.");
}
}
I am using below dependencies:
<!-- 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>
It gives exception as:
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)
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<String, String> {
@FunctionName("hello")
public void execute(@TimerTrigger(name = "timerInfo", schedule = "0 * * * * *") String timerInfo,
final ExecutionContext context){
context.getLogger().info("Executing the function..."+variable);
context.getLogger().info(System.getenv("VARIABLE"));
super.handleRequest(timerInfo, context); // this is correct way to invoke your Spring Cloud function.
context.getLogger().info("Here I am...");
}
}
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: "+user.getId());
}
context.getLogger().info("Process Finished.");
return "";
};
}
}
答案2
得分: 0
不确定为什么它不起作用,看起来是正确的。我在演示中尝试了@Value
和System.getenv()
,它们都运行良好。
如果在环境变量中找不到键(VARIABLE),你将会收到以下异常信息
java.lang.IllegalArgumentException: 无法在字符串值"${XXX}"中解析占位符"XXX"。
因此,在您的方法hello()
中似乎会得到空指针异常,尝试逐步调试该方法,也许会发生在user.getId()
处。
英文:
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()
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论