在我的论文中,我正在用Vaadin和Spring做一个订单管理web应用程序。
@Slf4j
@Route("app/end-user/sent")
public class SentToRestaurantView extends EndUserViewBase {
Registration broadcasterRegistration;
public SentToRestaurantView() {
super("Sent to restaurant");
add(
new H1("Your order has been sent"),
new H2("The restaurant has received your order. They will respond with a time estimate in a few minutes.")
);
}
private void onUpdate(String message) {
// here is the redirect
UI.getCurrent().navigate(InTheMakingView.class);
log.info(message);
}
@Override
protected void onAttach(AttachEvent attachEvent) {
UI ui = attachEvent.getUI();
broadcasterRegistration = Broadcaster.register(newMessage -> ui.access(() -> onUpdate(newMessage)));
}
@Override
protected void onDetach(DetachEvent detachEvent) {
broadcasterRegistration.remove();
broadcasterRegistration = null;
}
}
用户在将订单发送到餐厅后将获得此视图。如果餐厅接受它(并广播消息),我希望将用户重定向到另一个视图;您可以在SentToRestaurantView::onUpdate中看到这一点。问题是,在重定向过程中,会发生错误。
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.example.demo.ui.enduser.view.InTheMakingView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.ui.enduser.view.InTheMakingView]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:315) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:296) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:332) ~[spring-beans-5.3.12.jar:5.3.12]
at com.vaadin.flow.spring.SpringInstantiator.getOrCreate(SpringInstantiator.java:117) ~[vaadin-spring-18.0.0.jar:na]
at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:193) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:135) ~[flow-server-8.0.4.jar:8.0.4]
at java.base/java.util.Optional.orElseGet(Optional.java:364) ~[na:na]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:134) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.sendBeforeEnterEventAndPopulateChain(AbstractNavigationStateRenderer.java:488) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.createChainIfEmptyAndExecuteBeforeEnterNavigation(AbstractNavigationStateRenderer.java:469) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:207) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.internal.JavaScriptNavigationStateRenderer.handle(JavaScriptNavigationStateRenderer.java:79) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.internal.JavaScriptBootstrapUI.handleNavigation(JavaScriptBootstrapUI.java:315) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.internal.JavaScriptBootstrapUI.navigate(JavaScriptBootstrapUI.java:223) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.navigate(UI.java:917) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.navigate(UI.java:898) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.navigate(UI.java:834) ~[flow-server-8.0.4.jar:8.0.4]
at com.example.demo.ui.enduser.view.SentToRestaurantView.onUpdate(SentToRestaurantView.java:31) ~[classes/:na]
at com.example.demo.ui.enduser.view.SentToRestaurantView.lambda$onAttach$b3eb7f9f$1(SentToRestaurantView.java:38) ~[classes/:na]
at com.vaadin.flow.component.UI.accessSynchronously(UI.java:446) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.access$000(UI.java:97) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI$2.execute(UI.java:521) ~[flow-server-8.0.4.jar:8.0.4]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) ~[na:na]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2039) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.server.VaadinSession.unlock(VaadinSession.java:720) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.server.VaadinService.ensureAccessQueuePurged(VaadinService.java:2005) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.server.VaadinService.accessSession(VaadinService.java:1972) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.server.VaadinSession.access(VaadinSession.java:1023) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.access(UI.java:518) ~[flow-server-8.0.4.jar:8.0.4]
at com.vaadin.flow.component.UI.access(UI.java:501) ~[flow-server-8.0.4.jar:8.0.4]
at com.example.demo.ui.enduser.view.SentToRestaurantView.lambda$onAttach$0(SentToRestaurantView.java:38) ~[classes/:na]
at com.example.demo.backend.broadcast.Broadcaster.lambda$broadcast$0(Broadcaster.java:26) ~[classes/:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.demo.ui.enduser.view.InTheMakingView]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:224) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117) ~[spring-beans-5.3.12.jar:5.3.12]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:311) ~[spring-beans-5.3.12.jar:5.3.12]
... 39 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.security.core.Authentication.getPrincipal()" because the return value of "org.springframework.security.core.context.SecurityContext.getAuthentication()" is null
at com.example.demo.security.user.enduser.service.details.EndUserDetailsServiceImpl.getUser(EndUserDetailsServiceImpl.java:19) ~[classes/:na]
at com.example.demo.ui.enduser.view.EndUserViewBase.<init>(EndUserViewBase.java:21) ~[classes/:na]
at com.example.demo.ui.enduser.view.InTheMakingView.<init>(InTheMakingView.java:18) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480) ~[na:na]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:211) ~[spring-beans-5.3.12.jar:5.3.12]
... 41 common frames omitted
@Route("app/end-user/waiting")
@Slf4j
public class InTheMakingView extends EndUserViewBase {
@Autowired
public InTheMakingView(EndUserDetailsService endUserDetailsService) {
super("In the making");
var order = endUserDetailsService.getUser().getTable().getOrderSession().getLastOrder();
add(
new H1("Your order is in the making"),
new H2(String.format("In about %d minutes our college, %s, will serve you your meal", order.getEstimatedTimeOfDoingInMinutes(), order.getServer().getName()))
);
}
}
@Slf4j
public abstract class EndUserViewBase extends ViewBase {
protected EndUserViewBase(String title) {
super(title);
var detailsService = BeanUtil.getBean(EndUserDetailsService.class);
add(
new Header(String.format(
"%s | %s",
detailsService.getUser().getTable().getRestaurant().getName(),
title))
);
}
}
显然,在EndUserDetaulsService方法中对EndUserDetaulsService的调用在EndUserViewBase的构造函数中返回null。刷新页面后,它将按预期工作。
@Service
@Slf4j
public class EndUserDetailsServiceImpl implements EndUserDetailsService{
@Autowired
EndUserService endUserService;
@Override
public EndUser getUser() {
var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userId = "";
// TOPIC pattern matching
if (principal instanceof UserDetails userDetails) {
userId = userDetails.getUsername();
}
var user =
endUserService.getUser(userId);
if (user.isEmpty()) {
throw new RuntimeException(String.format("User with email %s was not found", userId));
} else {
return user.get();
}
}
}
我无法找出此错误的来源,以及它如何与导航相关,或者为什么不显化,如果我重新加载页面,这是以前崩溃的。
发布于 2022-03-28 07:40:11
您的EndUserDetailsServiceImpl
是单例服务,因此SecurityContextHolder
是不可用的。您需要重构您的代码,以便在服务中不使用SecurityContextHolder
。您需要将userId
作为参数传递。
public EndUser getUser(String userId) {
// TOPIC pattern matching
if (principal instanceof UserDetails userDetails) {
userId = userDetails.getUsername();
}
var user =
endUserService.getUser(userId);
if (user.isEmpty()) {
throw new RuntimeException(String.format("User with email %s was not found", userId));
} else {
return user.get();
}
}
即从主体获取userId
,然后调用该方法。
public InTheMakingView(EndUserDetailsService endUserDetailsService) {
super("In the making");
var principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String userId = "";
// TOPIC pattern matching
if (principal instanceof UserDetails userDetails) {
userId = userDetails.getUsername();
}
var order = endUserDetailsService.getUser(userId).getTable().getOrderSession().getLastOrder();
add(
new H1("Your order is in the making"),
new H2(String.format("In about %d minutes our college, %s, will serve you your meal", order.getEstimatedTimeOfDoingInMinutes(), order.getServer().getName()))
);
}
https://stackoverflow.com/questions/71639894
复制相似问题