0

我们使用带有休眠数据库映射的 Spring Boot。实体包含映射为使用package-info.java文件定义的自定义类型的 JSON 列。

当我们从 Eclipse IDE 运行 spring-project 时,一切正常,我们可以调用我们的 Web 服务。

当我们生成一个可执行 jar 并尝试调用我们的 Web 服务时,会引发以下错误:

mai 04, 2017 1:35:00 PM org.apache.catalina.core.StandardWrapperValve invoke
GRAVE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: Unable to execute job Test] with root cause
java.lang.NoClassDefFoundError: BOOT-INF/classes/com/test/package-info (wrong name: com/test/package-info)
    at java.lang.ClassLoader.defineClass1(Native Method)

文件 package-info.class 进入 jar BOOT-INF/classes/com/test/package-info 有什么问题?

谢谢你的帮助

4

6 回答 6

5

我通过禁用包扫描和自动检测分类为 Hibernate 解决了这个问题

<persistence-unit name="sqlProvider" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>     
    <class>com.example.package.dao</class>

    .........     
    <properties>
        <property name="exclude-unlisted-classes" value="true"/>
        <property name="hibernate.archive.autodetection" value="hbm" />
        .........
    </properties>
    .........
</persistence-unit>
于 2017-10-19T19:45:05.550 回答
1

我不想禁用扫描,因为手动添加所有类persistence.xml不是一个选项。由于我们实际上并没有在我们的项目中为休眠使用包级别的注释,所以我创建了这个小可憎:

package com.example;

import org.hibernate.boot.archive.scan.internal.ScanResultImpl;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.ScanEnvironment;
import org.hibernate.boot.archive.scan.spi.ScanOptions;
import org.hibernate.boot.archive.scan.spi.ScanParameters;
import org.hibernate.boot.archive.scan.spi.ScanResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;

public class HibernateHackScanner extends StandardScanner {

    private static final Logger log = LoggerFactory.getLogger(HibernateHackScanner.class);

    @Override
    public ScanResult scan(ScanEnvironment environment, ScanOptions options, ScanParameters parameters) {
        log.info("Hack-Scanner is active, annotated packages will not be found by this scanner.");
        ScanResult scan = super.scan(environment, options, parameters);
        return new ScanResultImpl(Collections.emptySet(), scan.getLocatedClasses(), scan.getLocatedMappingFiles());
    }
}

然后我在以下位置启用了这个自定义扫描仪persistence.xml

<property name="hibernate.archive.scanner" value="com.example.HibernateHackScanner"/>

该扫描仪在引擎盖下使用标准扫描仪,并简单地丢弃所有boot_inf.classes在其包中附加了 etc. 的注释包。但是,如果您确实需要包级别的注释,则需要比这个拐杖更复杂一些。但这对我有用¯\_(ツ)_/¯

于 2018-01-30T13:44:56.293 回答
1

Nestor Fedyk 解决方案帮助我解决了这个问题。

请在下面找到代码,我已将解决方案添加到我的休眠配置文件中

添加了“排除未列出的类”“hibernate.archive.autodetection”属性

  <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="rcsDataSource"/>
    <property name="persistenceUnitName" value="corePersistenceUnit"/>
    <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.query.factory_class">org.hibernate.hql.internal.classic.ClassicQueryTranslatorFactory</prop>
            <prop key="hibernate.cache.use_second_level_cache">false</prop>
            <prop key="hibernate.cache.use_query_cache">false</prop>
            <prop key="hibernate.cache.region.factory_class">xxxx.xxxxxxxx.xxxx</prop>
            <prop key="hibernate.cache.provider_class">xxx.xxxxxxxx.xxxx</prop>
            <prop key="hibernate.cache.use_structured_entries">false</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.default_batch_fetch_size">250</prop>            
            <prop key="hibernate.max_fetch_depth">5</prop>            
            <prop key="hibernate.jdbc.fetch_size">300</prop>
            <prop key="exclude-unlisted-classes">true</prop>
            <prop key="hibernate.archive.autodetection">"hbm"</prop>
        </props>
    </property>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

我希望这有帮助

于 2019-09-11T15:08:25.173 回答
0

cxf-codegen-plugin用来生成实体。在我的情况下,排除package-info类解决了这个问题。我package-info.class从项目文件中删除,将额外参数添加到 pom 文件中,例如:

 <plugin>
                <groupId>org.apache.cxf</groupId>
                <artifactId>cxf-codegen-plugin</artifactId>
                <version>${cxf.version}</version>

                <executions>
                          <execution>
                            <id>mvn s</id>
                            <phase>generate-sources</phase>
                            <configuration>
                                <sourceRoot>${project.build.directory}/generated/cxf</sourceRoot>
                                <sourceRoot>${basedir}/src/main/java</sourceRoot>
                                <wsdlOptions>
                                    <wsdlOption>
                                        <wsdl>${basedir}/src/main/resources/wsdl/YOURWSDL.wsdl</wsdl>
                                        <wsdlLocation>classpath:wsdl/YOURWSDL.wsdl</wsdlLocation>

                                        <bindingFiles>
                                            <bindingFile>${basedir}/src/main/resources/wsdl/bindings.xml</bindingFile>
                                        </bindingFiles>

                                    </wsdlOption>

                                    <wsdlOption>
                                        <wsdl>${basedir}/src/main/resources/wsdl/YOURWSDL.wsdl</wsdl>
                                        <!--<extraargs>-->
                                            <!--<extraarg>-impl</extraarg>-->
                                            <!--<extraarg>-server</extraarg>-->
                                        <!--</extraargs>&ndash;&gt;-->
                                    </wsdlOption>
                                </wsdlOptions>

                                <defaultOptions>
                                    <extraargs>
                                        <extraarg>-xjc-npa</extraarg>
                                    </extraargs>
                                </defaultOptions>

                            </configuration>
                            <goals>
                                <goal>wsdl2java</goal>
                            </goals>
                        </execution>
                </executions>
            </plugin>

和包文件:mvn clean install spring-boot:repackage -DskipTests. 现在它工作正常。

于 2018-05-14T06:59:46.727 回答
0

我设法通过修改 Jan Thomä 的解决方案使其工作:

package com.example;

import org.hibernate.boot.archive.scan.internal.PackageDescriptorImpl;
import org.hibernate.boot.archive.scan.internal.ScanResultImpl;
import org.hibernate.boot.archive.scan.internal.StandardScanner;
import org.hibernate.boot.archive.scan.spi.*;
import org.hibernate.boot.archive.spi.ArchiveDescriptorFactory;

import java.util.Set;
import java.util.stream.Collectors;

public class CustomHibernateScanner extends StandardScanner {

    private static final String SPRING_BOOT_JAR_PREFIX = "BOOT-INF.classes.";

    public CustomHibernateScanner() {
    }

    public CustomHibernateScanner(ArchiveDescriptorFactory value) {
        super(value);
    }

    @Override
    public ScanResult scan(ScanEnvironment environment, ScanOptions options, ScanParameters parameters) {
        ScanResult result = super.scan(environment, options, parameters);
        Set<PackageDescriptor> pkgDesc = result.getLocatedPackages().stream()
                .map(this::fixPackageDescriptor)
                .collect(Collectors.toSet());
        return new ScanResultImpl(pkgDesc,
                result.getLocatedClasses(),
                result.getLocatedMappingFiles());
    }

    private PackageDescriptor fixPackageDescriptor(PackageDescriptor pd) {
        if (pd.getName().startsWith(SPRING_BOOT_JAR_PREFIX)) {
            return new PackageDescriptorImpl(pd.getName().substring(SPRING_BOOT_JAR_PREFIX.length()), pd.getStreamAccess());
        }
        return pd;
    }

}

它被添加到persistence.xml原始答案中。它基本上删除了导致异常的包描述符名称中的前缀。这样,它就可以工作,并且不需要禁用包扫描。

于 2020-11-26T11:45:40.353 回答
-1

package-info您可以在外部 jar中提取包含 JAXB 生成的类的包(即包含该类的包)。将与 JAXB 相关的资源(例如,XSD 文件)也移动到新项目。

现在您可以将这样的 jar 设置为生成可执行 jar 的项目的依赖项。

这样,当我从命令行运行我的 Spring Batch/Spring Boot 项目时,它就可以工作。我知道这不是最佳解决方案,但就我而言,它有效。

于 2017-09-12T06:23:14.820 回答