我在尝试将 RabbitMQ 队列消息传递到我的 Spring Boot 应用程序时遇到了问题。我正在运行 spring data 4 并使用 Neo4j 作为我的数据库。我能够接收并解析从 RabbitMQ 队列到 spring boot 应用程序的 JSON 字符串。这是接收进程的线程更改:
14:19:17.811 [main] INFO o.s.b.c.e.t.TomcatEmbeddedServletContainer - Tomcat 在端口上启动:8080 (http)
14:19:17.813 [main] INFO org.directoryx.Application - 在 4.989 秒内启动应用程序(JVM 运行 5.47)
14:19:26.708 [SimpleAsyncTaskExecutor-1] 信息 org.directoryx.sync.Receiver - 已收到消息! {"lastName":"Okuneva", "country":"United States", "city":"New Stantonfort","org":"IT","photo":"profile9.jpg",
"active":"true", "managerId":"1502", "title":"Global Integration Orchestrator", "userId":"frokune", "firstName":"Frank",
"phone":"(485)544-1782 x913", "id":"6791", "email":"frokune@peoplemaker.com","status":"员工"}
14:19:26.718 [SimpleAsyncTaskExecutor-1] INFO org.directoryx.sync.Receiver - 更新人员:Frank Okuneva
但是当我尝试将传入的 JSON 保存到 Neo4j 节点时,应用程序崩溃并出现以下错误:
线程“main”中的异常 org.springframework.beans.factory.BeanCreationException:创建名为“receiver”的 bean 时出错:注入(inject) Autowiring 的依赖项失败;嵌套异常是 org.springframework.beans.factory.BeanCreationException:无法 Autowiring 字段:private org.springframework.data.neo4j.template.Neo4jTemplate
在实现 neo4jTemplate 之前,当我尝试通过我的 personService->personServiceImpl->personRepository 模式保存人员时遇到此错误。
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.getSession': 当前线程的范围 'session' 不活跃;如果您打算从单例中引用它,请考虑为该 bean 定义一个作用域代理;嵌套异常是 java.lang.IllegalStateException:未找到线程绑定(bind)请求:您指的是实际 Web 请求之外的请求属性,还是在原始接收线程之外处理请求?如果您实际上是在 Web 请求中操作并且仍然收到此消息,则您的代码可能在 DispatcherServlet/DispatcherPortlet 之外运行:在这种情况下,请使用 RequestContextListener 或 RequestContextFilter 来公开当前请求。
下面是涉及的三个类:
Receiver.java
@Service
public class Receiver implements MessageListener {
static Logger log = LoggerFactory.getLogger(Receiver.class);
// Fails to be injected...
// Injection of autowired dependencies failed; nested exception is
// org.springframework.beans.factory.BeanCreationException: Could not autowire field:
@Autowired
private Neo4jTemplate neo4jTemplate;
public void onMessage(Message message) {
Gson gson = new GsonBuilder().create();
String msg = new String(message.getBody());
log.info("Message Recv'd! {}",msg);
Person person = gson.fromJson(msg, Person.class);
log.info("Update Person: {} {}", person.getFirstName(), person.getLastName());
try {
neo4jTemplate.save(person);
} catch (Exception e) {
log.error("Receiver failed to save Person: {}", e);
}
}
DataSyncConfig.java
@Configuration
public class DataSyncConfig {
@Autowired
RabbitTemplate rabbitTemplate;
private final String QUEUE_NAME = "sync2";
private final String ROUTING_KEY = "routeme";
private final boolean DURABLE = true;
private final boolean EXCLUSIVE = true;
private final boolean AUTO_DELETE = true;
@Bean
Queue queue() {
return new Queue(QUEUE_NAME, DURABLE, !EXCLUSIVE, !AUTO_DELETE);
}
@Bean
TopicExchange exchange() {
return new TopicExchange("etl-sync-tool");
}
@Bean
Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(ROUTING_KEY);
}
@Bean
public MessageConverter jsonMessageConverter() {
JsonMessageConverter jsonMessageConverter = new JsonMessageConverter();
return jsonMessageConverter;
}
@Bean
SimpleMessageListenerContainer container(ConnectionFactory connectionFactory, MessageListenerAdapter listenerAdapter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.setQueueNames(QUEUE_NAME);
container.setMessageListener(listenerAdapter);
return container;
}
@Bean
MessageListenerAdapter listenerAdapter(Receiver receiver) {
return new MessageListenerAdapter(receiver);
}
}
Neo4jConfig.java
@Configuration
@EnableNeo4jRepositories(basePackages = "org.directoryx.repository", queryLookupStrategy = QueryLookupStrategy.Key.CREATE_IF_NOT_FOUND)
@EnableTransactionManagement
public class Neo4jConfig extends Neo4jConfiguration {
private final Logger log = LoggerFactory.getLogger(Neo4jConfig.class);
@Resource
public Environment env;
@Override
@Bean
public Neo4jServer neo4jServer() {
log.info("Initialising Neo4j server connection...");
// username and password need to be available as System properties for Neo4j authentication.
String user = env.getProperty("neo4j.user");
System.setProperty("username", user);
String pass = env.getProperty("neo4j.pass");
System.setProperty("password", pass);
log.info("connecting as neo4j.user=" + user);
return new RemoteServer("http://localhost:7474");
}
@Override
@Bean
public SessionFactory getSessionFactory() {
log.info("Initialising Session Factory");
return new SessionFactory("org.directoryx.domain");
}
@Override
@Bean
// Unsure of scope value, tried both "session" and "global"
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public Session getSession() throws Exception {
log.info("Initialising session-scoped Session Bean");
return super.getSession();
}
@Bean
public Neo4jTemplate neo4jTemplate (Session session ) {
return new Neo4jTemplate(session);
}
}
我似乎无法找到如何通过公开和使用当前线程或通过创建新线程将数据保存到数据库。我觉得这是一个应该与 Spring Boot 和 Spring Data 的一些核心功能相差不远的问题,但即使经过广泛的研究,我似乎也无法确定使用什么语法。
最佳答案
错误消息表明在您的使用上下文中使用 session 范围运行不合适,可能是因为您在 RabbitMQ 上下文中而不是 Spring Web/MVC 上下文中。
我建议从 Neo4jConfig
中的 getSession
方法中完全删除 @Scope
注释,看看这是否会有所改善。如果您觉得有必要,以后可以随时添加用户管理的范围。
此外,您可能需要考虑针对 Neo4jOperations
而不是 Neo4jTemplate
进行编码。一些用户报告了注入(inject)类而不是接口(interface)的问题。
关于spring - RabbitMQ Spring Boot session 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31574417/