Java 條碼生成庫 Barcode4J Maven 依賴缺失錯誤 java.lang.IllegalStateException: Failed to introspect Class
前段時間專案中需要生成商品條碼,使用 Barcode4J 庫實現的,直接使用了內部的 BarcodeServlet ,僅在 Spring MVC 的 Controller 裡簡單的封裝了下提供個訪問路徑,使用上沒有遇到任何問題。程式碼如下:
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.krysalis.barcode4j.servlet.BarcodeServlet; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * <pre> * 條碼生成控制器 * 直接繼承barcode4j的BarcodeServlet實現 * </pre> */ @Controller @RequestMapping(value = "/barcode") public class BarcodeController extends BarcodeServlet { private static final long serialVersionUID = 2454174797419872114L; /** * <pre> * 根據 request 中傳遞的引數生成條碼,如:http://localhost/barcode/genbc?type=code128&msg=123456&ext=.svg * type:條碼型別,預設值為 code128 * msg:條碼號,預設值為 1234567890 * ext:輸入型別,預設值為 svg * 詳細文件:http://barcode4j.sourceforge.net/2.1/index.html * </pre> * @param request * @param response * @throws ServletException * @throws IOException */ @RequestMapping(value = "/genbc") public void genbc(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { super.doGet(request, response); } }
近期專案改造,由 Eclipse J2EE Web 改為 Gradle 構建方式。將所有WEB-INF\lib 下的 jar 根據經驗轉換為 build.gradle 配置檔案中的依賴配置,部分內容如下:
// 其他配置省略...
dependencies {
// 增加 barcode4j 依賴
compile 'net.sf.barcode4j:barcode4j:2.1'
// 其他依賴省略...
}
這個轉換過程中是會遇到很多問題的,就說 Barcode4J 的這個
2018-10-07 13:50:05.068 ERROR 12096 --- [ost-startStop-1] o.s.b.web.embedded.tomcat.TomcatStarter :
Error starting Tomcat context. Exception: org.springframework.beans.factory.BeanCreationException. Message:
Error creating bean with name 'barcodeController':
Lookup method resolution failed;
nested exception is java.lang.IllegalStateException:
Failed to introspect Class [org.krysalis.barcode4j.servlet.BarcodeServlet] from ClassLoader [ [email protected]]
這個錯誤很棘手,直接導致專案無法啟動,會影響團隊成員的開發工作。
原始的web專案中是直接將 jar 放入 lib 檔案下面,Barcode4J barcode4j-2.1.0 官方下載的裡面有所依賴的 jar,如下:
- avalon-framework-4.2.0.jar
- commons-cli-1.0.jar
- jdom-1.0.jar
- serializer-2.7.0.jar
- servlet-2.2.jar
- xalan-2.7.0.jar
- xml-apis-1.3.04.jar
而使用 Gradle barcode4j-2.1.0 的 Maven 依賴,如下:
<dependencies>
<dependency>
<groupId>avalon-framework</groupId>
<artifactId>avalon-framework-impl</artifactId>
<version>4.2.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.1</version>
</dependency>
</dependencies>
仔細的看的話就會發現 官網下載的包裡面是 avalon-framework-4.2.0,而使用 Maven 時裡面的卻是 avalon-framework-impl 4.2.0,在排除問題,讀 barcode4j 的 BarcodeServlet 原始碼時 IDEA 提示:
Cannot resolve symbol ‘Configuration’
Cannot resolve symbol ‘Logger’
意思是找不到 org.apache.avalon.framework.configuration.Configuration 與 org.apache.avalon.framework.logger.Logger 這兩個類。
檢視org.apache.avalon.framework.configuration內確實是沒有Configuration 這個類,如下圖:
檢視org.apache.avalon.framework.logger 內確實也沒有 Logger 這個類,如下圖:
既然這個依賴的名稱後面又 impl,那麼是否有介面呢?
查詢 Maven 庫 https://search.maven.org/classic/#search|ga|1|g%3A"avalon-framework" 有和 avalon-framework-impl 對應的 avalon-framework-api 而且版本也是一一對應的。
那麼就來看下 avalon-framework-api 裡面是否有這兩個疑似介面的類吧,如下圖:
果真在這裡面,那麼手動在 build.gradle 裡面加入 avalon-framework-api 依賴,如下:
// 其他配置省略...
dependencies {
// 增加 barcode4j 依賴
compile 'net.sf.barcode4j:barcode4j:2.1'
// 手動新增的 :avalon-framework-api 依賴
compile 'avalon-framework:avalon-framework-api:4.2.0'
// 其他依賴省略...
}
手動加入依賴後,重新編譯問題解決了。看來的確是 barcode4j 的依賴中缺少依賴 avalon-framework-api 。
那麼,為什麼下載的 barcode4j-2.1.0-bin.zip 中的 lib 資料夾內的 avalon-framework-4.2.0.jar 就好使呢?看了下 avalon-framework-4.2.0.jar 的檔案是85KB ,而依賴下載的
avalon-framework-api-4.2.0.jar 是 34KB 和 avalon-framework-impl-4.2.0.jar 是 60KB。由此看來應該是 avalon-framework-4.2.0.jar 裡面包含了 avalon-framework-api-4.2.0.jar 和 avalon-framework-impl-4.2.0.jar 的內容。