问题
We use Spring boot with hibernate database mapping. The entities contains JSON columns mapped as a customized types defined using package-info.java file.
When we run the spring-project from Eclipse IDE everything is ok and we can call our web services.
When we generate an executable jar and we try to call our web services the following error is raised :
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)
The file package-info.class is into the jar BOOT-INF/classes/com/test/package-info What can be wrong ?
Thanks for any help
回答1:
I solved this issue by disabling package scan and autodetection of classed for 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>
回答2:
I didn't want to disable scanning as manually adding all classes to persistence.xml
wasn't an option. Since we do not actually use package level annotations for hibernate in our project, I created this little abomination:
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());
}
}
Then I enabled this custom scanner in persistence.xml
:
<property name="hibernate.archive.scanner" value="com.example.HibernateHackScanner"/>
This scanner uses the standard scanner under the hood and simply discards all annotated packages which have boot_inf.classes
etc. prepended to their package. If you actually need package level annotations you would need to get a bit more sophisticated than this crutch, though. But this works for me ¯\_(ツ)_/¯
回答3:
I use cxf-codegen-plugin
to generate entites. In my case excluding package-info
class solved the problem. I deleted package-info.class
from project file, add extraargs to pom file like:
<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>–>-->
</wsdlOption>
</wsdlOptions>
<defaultOptions>
<extraargs>
<extraarg>-xjc-npa</extraarg>
</extraargs>
</defaultOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
and package file: mvn clean install spring-boot:repackage -DskipTests
. Now it works fine.
回答4:
Nestor Fedyk solution helped me in resolving the issue.
please find the code below, i have added the solution to my hibernate config file
"exclude-unlisted-classes" "hibernate.archive.autodetection" properties added
<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>
I hope this helps
回答5:
You can extract the package containing the JAXB generated classes (that is the package containing the package-info
class) in an external jar. Move to the new project the JAXB related resources, too (e.g., the XSD file).
Now you can set such a jar as a dependency of the project producing the exacutable jar.
This way, my Spring Batch/Spring Boot project works when I run it from command line. I'm aware that it's not an optimal solution but, in my case, it works.
来源:https://stackoverflow.com/questions/43782191/spring-boot-runnable-jar-cant-load-package-info-class