ejb.jar情况下mybatis没有初始化
mybatis is not initialized in case of ejb.jar
看来我所做的还不完整,我的代码中还缺少一些东西。
我想在 EJB 中使用 MyBatis + mybatis-cdi。我的 jar 仅包含一个无状态 ejb class 和一个会话工厂生产者 class。我认为问题在于我的 MyBatis 会话工厂生产者从未被 EE 容器调用(我在日志文件中看不到“MyBatis SessionFactory is initializing...
”日志条目)。
部署时出现以下错误:
WELD-001408: Unsatisfied dependencies for type ConfigurationDao with qualifiers @Default at injection point ....
当我将相同的 classes(EJB + 会话工厂生产者 classes)打包到 war 时,我可以在日志中看到会话工厂生产者被调用。但是我需要将它们打包到一个简单的 ejb 而不是 war,因为我正在构建一个 EJB 服务,它被另一个 wars 使用。
这是我的装配结构:
EAR
+--- commons.jar (interfaces)
+--- configuration-service.jar (stateless ejb + mybatis mapper interface + session factory producer)
+--- restapi-1.war
+--- restapi-2.war
以下classes 坐在配置-service.jar:
Session Factory 制作人
//@Stateless
public class SessionFactoryProducer {
private static final Logger LOGGER = ...;
@ApplicationScoped
@Produces
@SessionFactoryProvider
public SqlSessionFactory produce() throws Exception {
LOGGER.info("MyBatis SessionFactory is initializing...");
try (Reader reader = Resources.getResourceAsReader("mybatis.xml")) {
return new SqlSessionFactoryBuilder().build(reader);
}
}
}
无状态 ejb
@Stateless
public class ConfigurationBean implements ConfigurationService {
@Inject
private ConfigurationDao configurationDao;
public void setStringValue(final Configuration configuration) {
...
// save to database
configurationDao.insert(configuration);
...
}
public String getStringValue(final String key) {
return configurationDao.findByKey(key).map(Configuration::getValue).orElse(null);
}
}
MyBatis 映射器:
@Mapper
public interface ConfigurationDao {
@Select("SELECT ...")
Configuration findByKey(@Param("key") String key);
@Insert("INSERT INTO ...")
void insert(Configuration configuration);
}
用法来自 war(球衣休息)
@Path("/")
public class MyClass {
@Inject
private ConfigurationService configurationService;
@GET
@Produces(MediaType.APPLICATION_UTF8_JSON)
public String doSomething() {
String something = configurationService.getStringValue(KEY);
...
}
}
对于我的 ear/ejb 应用程序,这是我声明 SessionFactoryProvider 的方式:
@Local(ISqlSessionFactoryProvider.class)
@Stateless
public class SqlSessionFactoryProvider implements ISqlSessionFactoryProvider
@Local
public interface ISqlSessionFactoryProvider {
SqlSessionFactory produceFactory() throws IOException;
}
然后在 EJB 中,我注入 SqlSession 并从中检索 Mapper。但是直接注入映射器应该按照 documentation.
中指定的方式工作
在我的另一个应用程序:一个简单的网络应用程序中,我声明 SessionFactoryProvider 的方式与您相同。
这可能不是最好的方法,但它确实有效。
我认为存在文件 "empty" beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file can be an empty text file (0 bytes) -->
<!-- We're declaring the schema to save you time if you do have to configure
this in the future -->
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
在 WEB-INF(对于 webapp)或 META-INF(对于 ejb-jar)目录中可能允许容器服务器active/load一些东西。
我刚刚 checked:它 开启 CDI 。
我实际上用它来声明不应该相关的 TransactionInterceptor。
看来我所做的还不完整,我的代码中还缺少一些东西。
我想在 EJB 中使用 MyBatis + mybatis-cdi。我的 jar 仅包含一个无状态 ejb class 和一个会话工厂生产者 class。我认为问题在于我的 MyBatis 会话工厂生产者从未被 EE 容器调用(我在日志文件中看不到“MyBatis SessionFactory is initializing...
”日志条目)。
部署时出现以下错误:
WELD-001408: Unsatisfied dependencies for type ConfigurationDao with qualifiers @Default at injection point ....
当我将相同的 classes(EJB + 会话工厂生产者 classes)打包到 war 时,我可以在日志中看到会话工厂生产者被调用。但是我需要将它们打包到一个简单的 ejb 而不是 war,因为我正在构建一个 EJB 服务,它被另一个 wars 使用。
这是我的装配结构:
EAR
+--- commons.jar (interfaces)
+--- configuration-service.jar (stateless ejb + mybatis mapper interface + session factory producer)
+--- restapi-1.war
+--- restapi-2.war
以下classes 坐在配置-service.jar:
Session Factory 制作人
//@Stateless
public class SessionFactoryProducer {
private static final Logger LOGGER = ...;
@ApplicationScoped
@Produces
@SessionFactoryProvider
public SqlSessionFactory produce() throws Exception {
LOGGER.info("MyBatis SessionFactory is initializing...");
try (Reader reader = Resources.getResourceAsReader("mybatis.xml")) {
return new SqlSessionFactoryBuilder().build(reader);
}
}
}
无状态 ejb
@Stateless
public class ConfigurationBean implements ConfigurationService {
@Inject
private ConfigurationDao configurationDao;
public void setStringValue(final Configuration configuration) {
...
// save to database
configurationDao.insert(configuration);
...
}
public String getStringValue(final String key) {
return configurationDao.findByKey(key).map(Configuration::getValue).orElse(null);
}
}
MyBatis 映射器:
@Mapper
public interface ConfigurationDao {
@Select("SELECT ...")
Configuration findByKey(@Param("key") String key);
@Insert("INSERT INTO ...")
void insert(Configuration configuration);
}
用法来自 war(球衣休息)
@Path("/")
public class MyClass {
@Inject
private ConfigurationService configurationService;
@GET
@Produces(MediaType.APPLICATION_UTF8_JSON)
public String doSomething() {
String something = configurationService.getStringValue(KEY);
...
}
}
对于我的 ear/ejb 应用程序,这是我声明 SessionFactoryProvider 的方式:
@Local(ISqlSessionFactoryProvider.class)
@Stateless
public class SqlSessionFactoryProvider implements ISqlSessionFactoryProvider
@Local
public interface ISqlSessionFactoryProvider {
SqlSessionFactory produceFactory() throws IOException;
}
然后在 EJB 中,我注入 SqlSession 并从中检索 Mapper。但是直接注入映射器应该按照 documentation.
中指定的方式工作在我的另一个应用程序:一个简单的网络应用程序中,我声明 SessionFactoryProvider 的方式与您相同。
这可能不是最好的方法,但它确实有效。
我认为存在文件 "empty" beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!-- This file can be an empty text file (0 bytes) -->
<!-- We're declaring the schema to save you time if you do have to configure
this in the future -->
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>
在 WEB-INF(对于 webapp)或 META-INF(对于 ejb-jar)目录中可能允许容器服务器active/load一些东西。 我刚刚 checked:它 开启 CDI 。
我实际上用它来声明不应该相关的 TransactionInterceptor。