Spring boot 在FUSE EAP环境中使用Springboot自动配置连接到SQL Server时出现问题

Spring boot 在FUSE EAP环境中使用Springboot自动配置连接到SQL Server时出现问题,spring-boot,sql-server-2012,redhat,jbossfuse,jboss-eap-7,Spring Boot,Sql Server 2012,Redhat,Jbossfuse,Jboss Eap 7,在FUSE EAP环境中使用SpringBoot时,这可能是我的一个误解。我一直在尝试部署一个服务,它是根据RedHat文档和我在网上找到的混合了Camel和SpringBoot的原型/示例开发的,但没有成功 据我所知,在创建到JNDI数据源的连接时(该数据源已在EAP Fuse服务器中配置和测试),我可以使用application.properties或application.yml让spring应用程序自动配置连接。在我的例子中,需要使用@PersistenceContext调用Entity

在FUSE EAP环境中使用SpringBoot时,这可能是我的一个误解。我一直在尝试部署一个服务,它是根据RedHat文档和我在网上找到的混合了Camel和SpringBoot的原型/示例开发的,但没有成功

据我所知,在创建到JNDI数据源的连接时(该数据源已在EAP Fuse服务器中配置和测试),我可以使用application.properties或application.yml让spring应用程序自动配置连接。在我的例子中,需要使用@PersistenceContext调用EntityManager,因为扩展JpaRepository的CRUD操作并不能真正满足需要

根据RedHat的文档,FUSE 7.2已安装在EAP 7.1中,POM使用org.jboss.RedHat-FUSE.FUSE-springboot-bom版本7.2.0.FUSE-720020-RedHat-00001

我尝试过使用spring的自动配置、声明@configuration类的手动配置、通过在camel-context.xml文件中声明数据库连接的手动配置,以及其他一些小测试

错误的大小取决于我是尝试对.jar还是.jar.original进行Delpy,这是由具有重新打包执行目标的spring boot maven插件生成的。到目前为止,获得的错误有:

  • 空指针,因为EntityManager em为空(.jar.original)
  • java.lang.NoClassDefFoundError:org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder(.jar.original,当有数据源的手动配置时,可以在@configuration注释的java类中,或者使用Spring DSL在camel-context.xml中)
  • java.lang.ClassNotFoundException:com.example.dao.genericDAOImpl(.jar,打包了所有依赖项)
下面是我的程序片段,包括POM、Application.java和试图获取EntityManager的组件,如果不够/不清楚,我很乐意提供更多片段

POM.xml

...
    <properties>
        <fuse.version>7.2.0.fuse-720020-redhat-00001</fuse.version>
        ...
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
    </dependencies>
...
<build>
        <defaultGoal>spring-boot:run</defaultGoal>
        <plugins>
            ...
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>1.5.16.RELEASE</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            ...
        </plugins>
    </build>
...
Application.java

@ImportResource({"classpath:spring/camel-context.xml"})
@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
camel-context.xml

<beans ...>
...
    <camelContext id="identidades_financieras" xmlns="http://camel.apache.org/schema/spring">
        <onException>
            <exception>java.lang.Exception</exception>
            <handled>
                <constant>true</constant>
            </handled>
            <setHeader headerName="Exchange.HTTP_RESPONSE_CODE">
                <constant>500</constant>
            </setHeader>
            <setBody>
                <simple>${exception.message}</simple>
            </setBody>
        </onException>
        <restConfiguration apiContextPath="/openapi.json"
            bindingMode="json" component="undertow"
            contextPath="/restservice/api_v1" enableCORS="true">
            <dataFormatProperty key="prettyPrint" value="true"/>
        </restConfiguration>
        <rest enableCORS="true" id="rest-for-openapi-document" path="/openapi">
            <get id="openapi.json" produces="application/json" uri="openapi.json">
                <description>Gets the OpenAPI document for this service</description>
                <route id="route-for-openapi-document">
                    <setHeader headerName="Exchange.CONTENT_TYPE" id="setHeader-for-openapi-document">
                        <constant>application/vnd.oai.openapi+json</constant>
                    </setHeader>
                    <setBody id="setBody-for-openapi-document">
                        <constant>resource:classpath:openapi.json</constant>
                    </setBody>
                </route>
            </get>
        </rest>
        <rest bindingMode="auto" enableCORS="true"
            id="rest-b5d099c1-1996-458b-b5db-34aadc57a548" path="/">
            <get id="customPaginatexxxVO" produces="application/json" uri="/xxx">
                <to uri="direct:customPaginatexxxVO"/>
            </get>
...

        <route id="route-28f4489d-b354-401b-b774-6425bec1c120">
            <from id="from-17c4205f-8d28-4d3d-a265-cb1c38c9bc32" uri="direct:customPaginatexxxVO"/>
            <log id="customPaginatexxxVO-log-1" message="headers ====> pageSize: ${header.pageSize} - pageNumber: ${header.pageNumber}"/>
            <bean id="to-ee6565efaf-de46-4941-b119-be7aaa07d892"
                method="paginate" ref="genericService"/>
            <log id="customPaginatexxxVO-log-2" message="${body}"/>
        </route>
<beans/>

使用手动配置的DataSource和EntityManagerFactory部署.jar.original(基本上就是java)时。据我所知,该服务期望服务器上存在org.springframework.boot依赖项。检查模块后,保险丝层中没有org.springframework.boot模块。这是有意的吗

09:50:17,265 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-8) MSC000001: Failed to start service jboss.deployment.unit."identidades_financieras-1.0-SNAPSHOT.jar".CamelContextActivationService."identidades_financieras-1.0-SNAPSHOT.jar": org.jboss.msc.service.StartException in service jboss.deployment.unit."identidades_financieras-1.0-SNAPSHOT.jar".CamelContextActivationService."identidades_financieras-1.0-SNAPSHOT.jar": Failed to start service
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1978)
    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.NoClassDefFoundError: org/springframework/boot/orm/jpa/EntityManagerFactoryBuilder
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.getDeclaredMethods(Class.java:1975)
    at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:613)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:524)
    at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:510)
    at org.springframework.util.ReflectionUtils.getUniqueDeclaredMethods(ReflectionUtils.java:570)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryMethod(AbstractAutowireCapableBeanFactory.java:697)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineTargetType(AbstractAutowireCapableBeanFactory.java:640)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.predictBeanType(AbstractAutowireCapableBeanFactory.java:609)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isFactoryBean(AbstractBeanFactory.java:1490)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:425)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:395)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:96)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:687)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:525)
    at org.wildfly.extension.camel.SpringCamelContextBootstrap$1.run(SpringCamelContextBootstrap.java:90)
    at org.wildfly.extension.camel.proxy.ProxyUtils$1.invoke(ProxyUtils.java:51)
    at com.sun.proxy.$Proxy68.run(Unknown Source)
    at org.wildfly.extension.camel.proxy.ProxyUtils.invokeProxied(ProxyUtils.java:55)
    at org.wildfly.extension.camel.SpringCamelContextBootstrap.createSpringCamelContexts(SpringCamelContextBootstrap.java:87)
    at org.wildfly.extension.camel.service.CamelContextActivationService.start(CamelContextActivationService.java:58)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:2032)
    at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1955)
    ... 3 more
Caused by: java.lang.ClassNotFoundException: org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder from [Module "deployment.identidades_financieras-1.0-SNAPSHOT.jar" from Service Module Loader]
    at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:412)
    at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:400)
    at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
    ... 27 more
最后,当仅使用Spring自动配置上传.jar.original时,EM为null,使用Postman时,我得到一个状态500,当我使用其余的时,“没有可用的响应”

java.lang.NullPointerException
at com.example.dao.genericDAOImpl.customPagination(GenericDAOImpl.java:252)
该行引用CriteriaBuilder paginationBuilder=em.getCriteriaBuilder(),或调用em方法的任何其他位置

@Repository
public class genericDAOImpl implements genericDAO {

    @PersistenceContext //when manually configured, I've added the (unitName="") in reference to the persistence unit, from my understanding, since only one datasource was created, this should pick up by default
    private EntityManager em;
...
    @Override
    public xxxVO customPagination(paginateProps pageProps) {
        xxxVO result = null;
        try {
            CriteriaBuilder paginationBuilder = em.getCriteriaBuilder();
            CriteriaQuery<T> paginationQuery = paginationBuilder.createQuery(entity.class);
            Root<T> entityClass = paginationQuery.from(entity.class);
            paginationQuery.select(entityClass);
            ... some settings with pageProps ...
            TypedQuery<T> query = em.createQuery(paginationQuery);
            entityList = query.getResultList();
            ... entityList is transformed to xxxVO ...
        } catch (Exception e) {
            LOG.error("caught something");
            e.printStackTrace();
        }
        return result;
    }   
...

谢谢你抽出时间!非常感谢您的评论…

不支持带保险丝EAP和Camel子系统的Spring引导。因此,为什么在Fuse模块层中看不到任何
org.springframework.boot
依赖项


如果要将Camel-Spring引导应用程序部署到EAP中,最好禁用Camel子系统进行部署,或者避免完全安装该子系统。

不支持使用Fuse-EAP和Camel子系统的Spring引导。因此,为什么在Fuse模块层中看不到任何
org.springframework.boot
依赖项


如果要将Camel-Spring引导应用程序部署到EAP中,最好禁用Camel子系统进行部署,或者避免完全安装该子系统。

这绝不是我遇到的问题的解决方案,我相信这只是我代码上的一个临时补丁,因为7.4版本的Fuse应该支持SpringBoot 2.1.x或类似的东西,但做以下操作可以创建数据库连接并继续我的生活。我不会认为这是可以接受的答案,除非有人告诉我这是唯一的办法

在Application.java中,我直接禁用了SpringBootServletilizer。完全公开,我不知道这样做会对应用程序产生什么影响,但在我尝试部署时,依赖性很麻烦

@ImportResource({"classpath:spring/camel-context.xml"})
@SpringBootApplication
public class Application {//extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
我创建了一个persistence.xml文件,在其中配置了持久化单元的名称,并选择了包含实体的包(或者列出了实体,两者都有效)

在camel-context.xml中,我在标记之前声明了以下内容

    <bean class="org.apache.camel.component.jpa.JpaComponent" id="jpa">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="transactionManager" ref="jpaTxManager"/>
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="jpaTxManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <bean
        class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="PERSISTENCE UNIT NAME IN PERSISTENCE.XML"/>
    </bean>
    <bean class="org.apache.camel.spring.spi.SpringTransactionPolicy" id="requiredPolicy">
        <property name="transactionManager" ref="jpaTxManager"/>
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
    </bean>
在需要数据库连接的bean中,在我的例子中,@组件(应该在@Repository中也能正常工作),我添加了以下内容:

    private IfEntityManagerImpl IfEntityManager;

    @PostConstruct
    public void init() {
         this.persistenceUnitEntityManagerImpl = new persistenceUnitEntityManagerImpl();
     }
无论何时需要调用EntityManager,我都可以使用PersistenceUnitEntityManager.getEntityManager()


为了确保组件没有创建新的连接/实体管理器/任何东西,您可以向@PostConstruct init添加一个日志,如果您的bean是单例(我相信默认情况下应该是单例),您将永远不会获得该日志或打印行

这绝不是我遇到的问题的解决方案,我相信这只是我代码上的一个临时补丁,因为7.4版本的Fuse应该支持SpringBoot 2.1.x或类似的东西,但做以下操作可以创建数据库连接并继续我的生活。我不会认为这是可以接受的答案,除非有人告诉我这是唯一的办法

在Application.java中,我直接禁用了SpringBootServletilizer。完全公开,我不知道这样做会对应用程序产生什么影响,但在我尝试部署时,依赖性很麻烦

@ImportResource({"classpath:spring/camel-context.xml"})
@SpringBootApplication
public class Application {//extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
我创建了一个persistence.xml文件,在其中配置了持久化单元的名称,并选择了包含实体的包(或者列出了实体,两者都有效)

在camel-context.xml中,我在标记之前声明了以下内容<
    <bean class="org.apache.camel.component.jpa.JpaComponent" id="jpa">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
        <property name="transactionManager" ref="jpaTxManager"/>
    </bean>
    <bean class="org.springframework.orm.jpa.JpaTransactionManager" id="jpaTxManager">
        <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
    <bean
        class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" id="entityManagerFactory">
        <property name="persistenceUnitName" value="PERSISTENCE UNIT NAME IN PERSISTENCE.XML"/>
    </bean>
    <bean class="org.apache.camel.spring.spi.SpringTransactionPolicy" id="requiredPolicy">
        <property name="transactionManager" ref="jpaTxManager"/>
        <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
    </bean>
@Stateless
public class persistenceUnitEntityManagerImpl implements IfEntityManager{


    private static EntityManager em;

    static {
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("PERSISTENCE UNIT NAME");
        em = entityManagerFactory.createEntityManager();
    }

    public void setEntityManager( EntityManager em ) {
        persistenceUnitEntityManagerImpl.em = em;
    }

    public EntityManager getEntityManager() {
        return persistenceUnitEntityManagerImpl.em;
    }
}
    private IfEntityManagerImpl IfEntityManager;

    @PostConstruct
    public void init() {
         this.persistenceUnitEntityManagerImpl = new persistenceUnitEntityManagerImpl();
     }