前言

在練習docker的時候,發現在docker容器一直啟動不了,
後來想說會不會是jar檔打包有問題,就一步一步找問題,最後發現是犯了很蠢的錯(?)


測試jar檔

打包前有先啟動本地的springboot看是正常啟動的
所以才會想說會不會是打包成jar檔時有東西沒放進去或是其他原因,
反正第一步先啟動看看:

假設專案打包好的jar名稱是 app.jar
使用指令:

1
java -jar app.jar

結果報出跟在docker一樣的錯誤

主控台顯示:

No active profile set, falling back to 1 default profile: >”default”

Error creating bean with name ‘xxxServiceImpl’ Unsatisfied dependency expressed through constructor parameter 0 …
Error creating bean with name ‘xxxServiceDao’ Unsatisfied dependency expressed through constructor parameter 0 …
defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to > bean ‘jpaSharedEM_entityManagerFactory’ while setting bean property ‘entityManager’


Debug 過程

(步驟莫名看起來有點像AI Agent的工作流程,但不是AI產是我自己想的ˋAˊ!!)

分析原因

拆成兩部份來看:

  1. 下面這段敘述是提醒沒有特別指定讀哪個properties,會採用預設的application.properties

    一般可能會額外有application-dev.properties或application-prod.properties
    No active profile set, falling back to 1 default profile: >”default”

  2. 主要的錯誤發生在這

    Error creating bean with name ‘xxxServiceImpl’ Unsatisfied dependency expressed through constructor parameter 0 …
    Error creating bean with name ‘xxxDao’ Unsatisfied dependency expressed through constructor parameter 0 …
    defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot resolve reference to > bean ‘jpaSharedEM_entityManagerFactory’ while setting bean property ‘entityManager’

主要敘述錯誤的原因很明顯就是:

  • bean沒有成功建立
    因為xxxServiceImpl 依賴xxxDao的注入,可是沒有成功注入

推理找出答案

一連串看下來源頭的罪魁禍首應該就是entity的問題
檢查:
✅ 該有的@component(or @Sevice) 有加
✅ 注入有正確注入 (我用建構子注入+lombok)
✅ lombok正常(編譯執行 不影響打包)
✅ @Entity 有加 table名稱column名稱也都正常

那我就想奇怪了(?) 程式看起來都很正常
於是我懷疑起了maven

重新執行clean > package之後發現,最下面的BUILD SUCCESS讓我以為沒有問題,
結果往上滑一看:
dependency.scope' for com.mysql:mysql-connector-j:jar must be one of [provided, compile, runtime, test, system]

scope ???!
我引入mysql的maven記得只有設版本呀 @A@?!
然後打開pom.xml一看
pom
原來我把 <version> 誤打成 <scope>


結論:把pom檔錯誤的部分修正

<scope>改為<version>就可以了

笑死 原來小丑是我自己 犯了低級錯誤 555

完美解決,我繼續去玩docker了 QQ
這個教訓告訴我,有時候不要太相信IDE server可以啟動,或者是看到SUCCESS 就是沒事(?)
要好好看每個過程,才不會想了一堆問題,結果其實早就有跡可循…


額外補充: maven打包自定義jar檔名稱

原始打包檔案名稱

一般springboot直接打包的話,他會照pom.xml上方專案的名稱,來命名打包後的檔名

1
2
<artifactId>test</artifactId>
<version>0.0.1-SNAPSHOT</version>

像這樣子打包完 會得到 test-0.0.1-SNAPSHOT.jar

可是有時候這樣很醜(?) 不是,是不好找!
我們可以自定義打包完的檔名是什麼,做法請往下看:


自定義打包檔案名稱

拉到pom檔最下面找到 <build>在裡面打上 your_file_name

1
2
3
4
<build>
<finalName>your_file_name</finalName>
...
</build>

這樣打包就會得到你自定義後的檔名了~


額外補充:檢查程式有沒有被打包進jar包

查詢指令:列出jar檔裡面的檔案結構

1
jar tf target/your_project.jar | grep xxxDao

| grep 同linux = 前面的輸出結果 傳到後面(|) 過濾關鍵字(grep)
就是查出jar檔底下的檔案結構 再查詢關鍵字