2025年3月19日 星期三

how to connect to Java DB from Java application or Java EE container

 假設 Java DB 已建好 db_name 資料庫,帳密為 user/password。

以下展示 Java EE 後台組件如何善用資料來源定義,注入資料來源,定義執行SQL指令,回傳結果集合給前台。

  1.  
  2. // 定義資料來源
  3. @DataSourceDefinition(
  4. name = "java:global/jdbc/db_name",
  5. className = "org.apache.derby.jdbc.ClientDataSource",
  6. url = "jdbc:derby://localhost:1527/db_name",
  7. databaseName = "db_name",
  8. user = "user",
  9. password = "password")
  10.  
  11. @Named("bean")
  12. @javax.faces.view.ViewScoped
  13. public class Bean implements Serializable
  14. {
  15. // 定義每筆記錄的欄位屬性 f1, f2, f3
  16.  
  17. // 要求伺服器注入資料來源成為 dataSource 物件
  18. @Resource(lookup="java:global/jdbc/db_name")
  19. DataSource dataSource;
  20. // 回傳查詢結果集合
  21. public ResultSet query() throws SQLException
  22. {
  23. // check whether dataSource was injected by the server
  24. if (dataSource == null)
  25. {
  26. throw new SQLException("Unable to obtain DataSource");
  27. }
  28. // 透過注入的資料來源,從連線池取得連線
  29. Connection connection = dataSource.getConnection();
  30.  
  31. // check whether connection was successful
  32. if (connection == null)
  33. {
  34. throw new SQLException("Unable to connect to DataSource");
  35. }
  36. try
  37. {
  38. // 建立查詢指令
  39. PreparedStatement getRecords = connection.prepareStatement(
  40. "SELECT * FROM tbl");
  41. // 建立存放結果的快取列集合
  42. CachedRowSet rowSet =
  43. RowSetProvider.newFactory().createCachedRowSet();
  44. // 執行查詢指令,將結果填入列集合
  45. rowSet.populate(getRecords.executeQuery());
  46.  
  47. // 回傳列集合,供前台呈現
  48. return rowSet;
  49. }
  50. finally
  51. {
  52. connection.close(); // return this connection to pool
  53. }
  54. }
  55. // 新增一筆記錄,回傳去處網頁名稱
  56. public String insert() throws SQLException
  57. {
  58. // check whether dataSource was injected by the server
  59. if (dataSource == null)
  60. {
  61. throw new SQLException("Unable to obtain DataSource");
  62. }
  63. // 透過注入的資料來源,從連線池取得連線
  64. Connection connection = dataSource.getConnection();
  65. // check whether connection was successful
  66. if (connection == null)
  67. {
  68. throw new SQLException("Unable to connect to DataSource");
  69. }
  70. try
  71. {
  72. // 建立帶參數新增記錄指令
  73. PreparedStatement addEntry =
  74. connection.prepareStatement("INSERT INTO tbl " +
  75. "(f1,f2,f3) VALUES (?, ?, ?)");
  76.  
  77. // 指定欄位值
  78. addEntry.setString(1, getF1());
  79. addEntry.setString(2, getF2());
  80. addEntry.setString(3, getF3());
  81.  
  82. addEntry.executeUpdate(); // insert the entry
  83. return ""; // 回傳空字串,停在原頁
  84. }
  85. finally
  86. {
  87. connection.close(); // 不管發生例外或return,都會關閉連線,歸還給連線池
  88. }
  89. }
  90. }
    利用 Java EE 後台注入資料來源的好處包括
  1. 連線池管理,可供連線重複使用,減少頻繁開關連線的成本。
  2. 資源管理,伺服器可管理連線生命週期,確保連線正常關閉,返回連線池。
  3. 組態管理,伺服器設定資料庫連線組態細節,程式只要呼叫資料來源即可。

如果願意喪失上述好處,也可採用

A. 單機版如DriverManager操作資料庫作法,一切自己管理,如下。

  1.  
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.SQLException;
  6. import java.sql.Statement;
  7.  
  8. public class JavaDBExample {
  9. private static final String DB_URL = "jdbc:derby:myDB;create=true";
  10. private static final String USER = "user";
  11. private static final String PASSWORD = "password";
  12.  
  13. public static void main(String[] args) {
  14. try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
  15. Statement stmt = conn.createStatement()) {
  16.  
  17. // Create a table
  18. String createTableSQL = "CREATE TABLE addresses (" +
  19. "id INT PRIMARY KEY, " +
  20. "firstname VARCHAR(255), " +
  21. "lastname VARCHAR(255), " +
  22. "street VARCHAR(255), " +
  23. "city VARCHAR(255), " +
  24. "state VARCHAR(255), " +
  25. "zip VARCHAR(255))";
  26. stmt.execute(createTableSQL);
  27.  
  28. // Insert data
  29. String insertSQL =
  30. "INSERT INTO addresses VALUES " +
  31. "(1, 'John', 'Doe', '123 Main St', 'Anytown', 'CA', '12345')";
  32. stmt.execute(insertSQL);
  33.  
  34. // Query data
  35. String querySQL = "SELECT * FROM addresses";
  36. ResultSet rs = stmt.executeQuery(querySQL);
  37.  
  38. while (rs.next()) {
  39. System.out.println("ID: " + rs.getInt("id"));
  40. System.out.println("First Name: " + rs.getString("firstname"));
  41. System.out.println("Last Name: " + rs.getString("lastname"));
  42. System.out.println("Street: " + rs.getString("street"));
  43. System.out.println("City: " + rs.getString("city"));
  44. System.out.println("State: " + rs.getString("state"));
  45. System.out.println("ZIP: " + rs.getString("zip"));
  46. }
  47. } catch (SQLException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }

或者,
B. 採用單機版Java Persistence API (JPA) 操作資料庫作法,如下。

  1. // Address.java 住址個體類別
  2.  
  3. import javax.persistence.Entity;
  4. import javax.persistence.Id;
  5. import javax.persistence.Table;
  6.  
  7. @Entity
  8. @Table(name = "addresses")
  9. public class Address {
  10. @Id
  11. private int id;
  12. private String firstname;
  13. private String lastname;
  14. String city;
  15. private String state;
  16. private String zip;
  17.  
  18. // Getters and setters
  19. }

由如下個體管理員建立查詢,取用資料庫:

  1. // JpaExample.java
  2.  
  3. import javax.persistence.EntityManager;
  4. import javax.persistence.EntityManagerFactory;
  5. import javax.persistence.Persistence;
  6. import javax.persistence.TypedQuery;
  7. import java.util.List;
  8.  
  9. public class JpaExample {
  10. private static final EntityManagerFactory ENTITY_MANAGER_FACTORY =
  11. Persistence.createEntityManagerFactory("myPersistenceUnit");
  12.  
  13. public static void main(String[] args) {
  14. EntityManager entityManager = ENTITY_MANAGER_FACTORY.createEntityManager();
  15.  
  16. try {
  17. // Create a query to fetch addresses
  18. TypedQuery<Address> query =
  19. entityManager.createQuery("SELECT a FROM Address a", Address.class);
  20. List<Address> addresses = query.getResultList();
  21.  
  22. // Process the result
  23. for (Address address : addresses) {
  24. System.out.println("ID: " + address.getId());
  25. System.out.println("First Name: " + address.getFirstname());
  26. System.out.println("Last Name: " + address.getLastname());
  27. System.out.println("Street: " + address.getStreet());
  28. System.out.println("City: " + address.getCity());
  29. System.out.println("State: " + address.getState());
  30. ();
  31. }
  32. } finally {
  33. entityManager.close();
  34. ENTITY_MANAGER_FACTORY.close();
  35. }
  36. }
  37. }

其中,建立個體管理員時,須要參考如下 META-INF/persistence.xml 持續組態檔,

內含 myPersistenceUnit 持續單元的定義:

  1. <persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence" version="2.2">
  2. <persistence-unit name="myPersistenceUnit">
  3. <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
  4. <class>com.example.Address</class>
  5. <properties>
  6. <property name="javax.persistence.jdbc.url" value="jdbc:derby:myDB;create=true"/>
  7. <property name="javax.persistence.jdbc.user" value="user"/>
  8. <property name="javax.persistence.jdbc.password" value="password"/>
  9. <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
  10. <property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
  11. <property name="hibernate.hbm2ddl.auto" value="update"/>
  12. </properties>
  13. </persistence-unit>
  14. </persistence>

2025年3月12日 星期三

a table summary of the javaserver faces 2.2 tag libraries defined in java ee 7

Java/Jarkarta EE 版本歷史所列,Java EE 7 標準發佈於 2013 年,伴隨的 JavaServer Faces 2.2 標準,已實作於 GlassFish 4.x 版本。其 .xhtml 網頁支援的標籤可參考 Oracle JavaEE 7 JSF 2.2 網站,共分成如下 6 種命名空間。

  • h: 為 JSF 超文字(html)標籤庫,提供標準 HTML 標籤的 JSF 版本,如 h:form、h:inputText 等,用於生成 HTML 表單元素。

  • f: 為 JSF 特殊功能(function)標籤庫,提供 JSF 的核心功能標籤,如 f:view、f:ajax、f:convertDateTime 等,用於處理事件、轉換器和 AJAX 功能。

  • ui: 為 JSF 配置用戶介面(user interface)標籤庫,提供模板和組合元件功能的標籤,如 ui:composition、ui:include、ui:repeat 等,用於定義和重複利用頁面結構。

  • c: 為 JSTL 核心(core)標籤庫,提供 JSTL的核心功能標籤,如 c:forEach、c:if、c:set 等,用於邏輯控制和迭代。

  • cc: 為 JSTL 組合元件(composite component)標籤庫,提供定義和使用組合元件的標籤,如 cc:interface、cc:implementation、cc:attribute 等,用於創建可重複利用的元件。

  • fn: 為 JSTL 函數(function)標籤庫,提供 JSTL 的函數標籤,如 fn:contains、fn:substring、fn:replace 等,用於字符串操作和其他常見功能。

其中,後面3種 JSTL (JavaServer Pages Standard Tag Library) 命名空間主要為了相容於早期發展的 JSP (JavaServer Pages) 網頁。以下針對 JSF (JavaServer Faces) 常見的前3種命名空間標籤,由 Miscosoft Copilot 摘要成表格如下。

h:命名空間標籤 描述
h:body 定義 HTML 文檔的主體。
h:button 渲染 HTML 按鈕。
h:column 定義數據表中的列。
h:commandButton 渲染可以提交表單的按鈕。
h:commandLink 渲染可以提交表單的鏈接。
h:dataTable 渲染數據表。
h:doctype 聲明文檔類型。
h:form 渲染 HTML 表單。
h:graphicImage 渲染圖像。
h:head 定義 HTML 文檔的頭部。
h:inputFile 渲染文件輸入字段。
h:inputHidden 渲染隱藏輸入字段。
h:inputSecret 渲染密碼輸入字段。
h:inputText 渲染文本輸入字段。
h:inputTextarea 渲染文本區輸入字段。
h:link 渲染超鏈接。
h:message 顯示單個驗證消息。
h:messages 顯示所有驗證消息。
h:outputFormat 渲染格式化文本。
h:outputLabel 為輸入字段渲染標籤。
h:outputLink 渲染超鏈接。
h:outputScript 渲染腳本。
h:outputStylesheet 渲染樣式表鏈接。
h:outputText 渲染文本。
h:panelGrid 渲染網格面板。
h:panelGroup 將組件分組在一起。
h:panelpassthrough.Element 渲染透傳元素。
h:selectBooleanCheckbox 渲染布爾值的複選框。
h:selectManyCheckbox 渲染多選複選框組。
h:selectManyListbox 渲染多選列表框。
h:selectManyMenu 渲染多選菜單。
h:selectOneListbox 渲染單選列表框。
h:selectOneMenu 渲染單選菜單。
h:selectOneRadio 渲染單選單選按鈕組。

f:命名空間標籤 描述
f:actionListener 為組件註冊一個動作監聽器。
f:ajax 為組件添加 Ajax 功能。
f:attribute 為組件添加一個屬性。
f:attributes 為組件添加多個屬性。
f:convertDateTime 將字符串轉換為日期/時間對象。
f:converter 為組件註冊一個轉換器。
f:convertNumber 將字符串轉換為數字。
f:event 為組件註冊一個事件監聽器。
f:facet 為組件聲明一個面。
f:loadBundle 加載資源包。
f:metadata 為視圖聲明元數據。
f:param 為組件添加一個參數。
f:passThroughAttribute 為組件添加一個透傳屬性。
f:passThroughAttributes 為組件添加多個透傳屬性。
f:phaseListener 為生命周期註冊一個階段監聽器。
f:resetValues 重置輸入組件的值。
f:selectItem 為選擇組件添加一個項目。
f:selectItems 為選擇組件添加多個項目。
f:setPropertyActionListener 當動作事件發生時設置屬性。
f:subview 在視圖中聲明一個子視圖。
f:validateBean 驗證一個 bean。
f:validateDoubleRange 驗證值是否在雙精度範圍內。
f:validateLength 驗證字符串的長度。
f:validateLongRange 驗證值是否在長整數範圍內。
f:validateRegex 根據正則表達式驗證字符串。
f:validateRequired 驗證值是否不為 null。
f:validator 為組件註冊一個驗證器。
f:valueChangeListener 為組件註冊一個值變更監聽器。
f:verbatim 渲染原始文本。
f:view 聲明一個視圖。
f:viewAction 聲明在視圖處理期間調用的動作。
f:viewParam 聲明一個視圖參數。

ui:命名空間標籤 描述
ui:component 定義可重用的組件,可以包含在其他頁面中。
ui:composition 定義頁面的模板,允許包含其他組件。
ui:debug 提供 JSF 頁面的調試信息。
ui:decorate 類似於 `ui:include`,但允許插入用戶定義的模板。
ui:define 定義模板的一部分,可以填充內容。
ui:fragment 定義頁面的一部分,可以包含在其他頁面中。
ui:include 包含另一個頁面或模板的內容。
ui:insert 將內容插入到模板的定義部分。
ui:param 將參數傳遞給包含的頁面或模板。
ui:remove 從渲染輸出中移除內容。
ui:repeat 對集合中的每個項目重複頁面的一部分。

2025年3月9日 星期日

Version history of Java EE, JPA, Java DB, JavaFX, and JDK

下表為 Java 平台企業版 (EE, Enterprise Edition) 各種開發工具的版本歷史。資料來自網路,可看出從昇陽公司的 J2EE、甲骨文公司的 Java EE,到 Eclipse基金會的 Jakarta EE,EE 標準的主導權不斷異動。 如果有機會拿到依據各代 Java 平台 EE 標準開發的舊程式碼,建議查找下表找出最合適的相關開發工具,以免無法進行測試。

例如,拿到使用 JavaFX 視窗介面程式,若查出其適用版本為 JavaFX 11,可參考下表得知,其合適的開發工具版本為 JavaFX 11  + JDK 11,兩者皆屬 LTS 長期支援版本,較容易找到安裝檔。

Year EE Standard JPA Java DB JavaFX JDK
1999J2EE 1.2
2000
J2SE 1.3
2001J2EE 1.3
2002
J2SE 1.4
2003J2EE 1.4
2004

J2SE 5 (1.5)
2005Java DB 10.1
2006Java EE 5JPA 1.0Java DB 10.2J2SE 6 (1.6)
2007
2008Java DB 10.3, 10.4JavaFX 1.0.2
2009Java EE 6JPA 2.0Java DB 10.5JavaFX 1.1, 1.2
2010Java DB 10.6JavaFX 1.3
2011
JavaFX 2.0J2SE 7 (1.7)
2012JavaFX 2.2
2013Java EE 7JPA 2.1Java DB 10.10
2014Java DB 10.11JavaFX 8J2SE 8 (1.8), LTS
2015Java DB 10.12
2016Java DB 10.13
2017Java EE 8JPA 2.2
J2SE 9 (1.9)
2018Java DB 10.14JavaFX 11 (LTS)J2SE 10 (1.10), J2SE 11 (LTS)
2019
Java DB 10.15JavaFX 12, 13J2SE 12, 13
2020Jakarta EE 9

JavaFX 14, 15J2SE 14, 15
2021Jakarta EE 9.1JavaFX 16, 17 (LTS)J2SE 16, J2SE 17 (LTS)
2022Jakarta EE 10JPA 3.1Java DB 10.16JavaFX 18, 19J2SE 18, 19
2023Java DB 10.17JavaFX 20, 21 (LTS)J2SE 20, J2SE 21 (LTS)
2024Jakarta EE 11JavaFX 23J2SE 22, 23
2025JavaFX 24, 25J2SE 24, J2SE 25 (LTS)

以下表格摘要,由 NetBeans 測試,可和各版本 JavaFX (LTS) 相容的長期支援 JDK (LTS) 版本,供安裝參考。

Year JavaFX (LTS) Compatible JDK (LTS) Note
2018JavaFX 11 (LTS)J2SE 11, 17, 21JDK 8 不支援 JavaFX 11 模組功能
2021JavaFX 17 (LTS)J2SE 11, 17, 21
2023JavaFX 21 (LTS)J2SE 17, 21JDK 11 不支援 JavaFX 21 模組版本

註1: 網路參考來源: 以 Wikipedia 維基百科網站為主

  1. Jakarta EE
  2. JPA
  3. Apache Derby (Java DB)
  4. JavaFX
  5. Java版本歷史

2025年2月21日 星期五

how to set up the NetBeans environment for running Java EE 7 compilant JavaServer Faces with @ManagedBean annotation

若拿到使用 JavaServer Faces (JSF) 開發的套件,內含 @ManagedBean 註記,可依據附註的部落格,查出其合適的開發工具版本為 JSF 2.0 + GlassFish 3.x + JDK 6 + NetBeans 6.x 或 JSF 2.2 + GlassFish 4.x + JDK 7 + NetBeans 7.x。

若找不到JDK 6、JDK 7,支援 LTS (長期服務) 版本的 JDK 8 較好找,應該也可以。至於 NetBeans 版本似乎較不嚴苛,使用較新的 NetBeans 22 也是可以的,只是伺服器要安裝支援 Java EE 6 或 7 的 GlassFish 及 JDK 版本。其安裝步驟如下

1. 假設 NetBeans 要安裝 GlassFish 4.1.2 (內含符合Java EE 7 Web標準的JSF2.2) + JDK 8
      所須 JDK 8 如下:
        OpenJDK Zulu 8.0.442+6
        zulu8.84.0.15-ca-jdk8.0.442-win_x64.zip
        C:\Users\xx\Documents\NetBeansJDKs\zulu8.84.0.15-ca-jdk8.0.442-win_x64\

2. 開舊專案後,改伺服器選用 Java EE 7 Web 相容的 GlassFish 4.1.12
      Resolve Missing Server Problem
        Available Java EE 7 Web compatible servers:
          GlassFish Server 4
     【OK】

3. 啟動 GlassFish Server 4
      Window/Services/Servers: GlassFish Server 4
        GlassFish server couldn ot be started with JDK XX (Default).
        Please select another Java SE Platform.
        Java Platform: Zulu 8.0.442+6
     【OK】

     Windoww安全性警訊
       Windows Defender 允許 OpenJDK xxx 在這些網路上通訊:
       V 網域網路,例如工作場所網路
    【允許存取】

4. 安裝 GlassFish 4.1.2 步驟
    Tools/Servers:
       Add Server...
         Choose Server
           Server: GlassFish Server
           Name: GlassFish Server 4
       Next>
         Server Location
           Installation Location: C:\Users\xx\GlassFish_server4
           X Local Domain
           Choose server to download:
             GlassFish Server 4.1.2
             V I have read and accept the licence agreement...(click)
             Download Now... (104.2m)
       Next>
         Domain Location
           Domain: domain1
           Host: localhost, Vloopback
           DAS Port: 4848, HTTP Port: 8080, VDefault
           Target:
           User Name:
           Password:
      【Finish】
    

        Server Name: GlassFish Server 4
        Server Type: GlassFish Server 4.1.2
        Common:
          Installation Location: C:\Users\xx\GlassFish_server4\glassfish
          Domains Folder: C:\Users\xx\GlassFish_server4\glassfish\domains
          Host: localhost
          DAS Port: 484, HTTP Port:8080
          Domain: domain1
            Enable HTTP Monitor (維持不打勾)
          V Enable JDBC Driver Deployment
          V Preserve Sessions Across Redeployment
          V Start Registered Derby Server
      【Close】

5. 安裝  JDK 8 方法
    Tools/Java Platforms
      Add Platform...
        Select platform type
          Download OpenJDK (via Foojay.io Disco API)
        Connect to OpenJDK Discovery Service
          Quick:
            Version: 23,21,17,11,8
            Distribution: Microsoft or Zulu

附註: 有關於 Java 平台企業版各種開發工具的歷史相容關係,可參考如下說明:
    Blog: Version history of Java EE,  JSF, GlassFish, JDK, and NetBeans

Version history of Java EE, JSF, GlassFish, JDK, and NetBeans

下表為 Java 平台企業版 (EE, Enterprise Edition) 各種開發工具的版本歷史。資料來自網路,可看出從昇陽公司的 J2EE、甲骨文公司的 Java EE,到 Eclipse基金會的 Jakarta EE,EE 標準的主導權不斷異動。 如果有機會拿到依據各代 Java 平台 EE 標準開發的舊程式碼,建議查找下表找出最合適的相關開發工具,以免無法進行測試。

例如,若拿到使用 JavaServer Faces (JSF) 開發的套件,內含 @ManagedBean 註記,可先查出其適用版本為 Java EE 6 或 Java EE 7。接著,參考下表得知,其合適的開發工具版本為 JSF 2.0 + GlassFish 3.x + JDK 6 + NetBeans 6.x 或 JSF 2.2 + GlassFish 4.x + JDK 7 + NetBeans 7.x。

其中,Java 開發套件 (Java Development Kit),簡稱 JDK,也歷經多代更迭。若找不到 JDK 6、JDK 7,支援 LTS (長期服務) 版本的 JDK 8 較好找,應該也可以。至於 NetBeans 版本的要求較不嚴苛,使用較新的 NetBeans 22 也是可以的,只是伺服器要安裝支援 Java EE 6 或 7 的 GlassFish 及 JDK 版本。

Year EE Standard JSF/Jakarta GlassFish JDK NetBeans
1999J2EE 1.2
2000J2SE 1.3
2001J2EE 1.3
2002J2SE 1.4
2003J2EE 1.4
2004JSF 1.0,1.1J2SE 5 (1.5)NetBeans 4.0
2005
2006Java EE 5JSF 1.2J2SE 6 (1.6)NetBeans 5.0
2007NetBeans 6.0
2008
2009Java EE 6JSF 2.0GlassFish 3.0
2010
2011J2SE 7 (1.7)NetBeans 7.0
2012
2013Java EE 7JSF 2.2GlassFish 4.0
2014J2SE 8 (1.8), LTSNetBeans 8.0
2015
2016
2017Java EE 8JSF 2.3J2SE 9 (1.9)
2018J2SE 10 (1.10), J2SE 11 (LTS)NetBeans 9.0, 10.0
2019Jakarta 2.3GlassFish 5.0J2SE 12, 13NetBeans 11.0
2020Jakarta EE 9Jakarta 3.0GlassFish 6.0J2SE 14, 15NetBeans 12.0
2021Jakarta EE 9.1J2SE 16, J2SE 17 (LTS)
2022Jakarta EE 10Jakarta 4.0GlassFish 7.0J2SE 18, 19NetBeans 13, 14, 15, 16
2023J2SE 20, J2SE 21 (LTS)NetBeans 17, 18, 19, 20
2024Jakarta EE 11J2SE 22, 23NetBeans 21, 22, 23, 24
2025J2SE 24, J2SE 25 (LTS)NetBeans 25, 26, 27, 28

以下表格摘要,由 NetBeans 測試,列出可和各版本 GlassFish 相容的長期支援 JDK (LTS) 版本,供安裝參考。

Year EE Standard JSF/Jakarta GlassFish Compatible JDK (LTS) Note
2009Java EE 6JSF 2.0GlassFish 3.0JDK 8
2013Java EE 7JSF 2.2GlassFish 4.0JDK 8支援 @ManagedBean 標註的最高版本組合
2019Java EE 8Jakarta 2.3GlassFish 5.0JDK 8@ManagedBean 廢止,改用環境及相依注入(CDI) 的 @Named 標註
2020Jakarta EE 9Jakarta 3.0GlassFish 6.0JDK 11, 17
2022Jakarta EE 10Jakarta 4.0GlassFish 7.0JDK 11, 17, 21

註1: Java EE 6,7 支援的 @ManagedBean 寫法,可參考如下要點,改成 Jakarta EE 支援的 @Named 註記。


  // 原來 Java EE 6,7 寫法
  import javax.faces.bean.ManagedBean;

  @ManagedBean(name="webBean")
  public class MyWebBean
  
  // 改成 Jakarta EE 寫法

  import jakarta.inject.Named;
  import jakarta.enterprise.context.SessionScoped;
  import java.io.Serializable;

  @Named("webBean")
  @SessionScoped
  public class MyWebBean implements Serializable

註2: 網路參考來源: 以 Wikipedia 維基百科網站為主

  1. Jakarta EE
  2. JavaServer Faces
  3. GlassFish
  4. Java版本歷史
  5. NetBeans
  6. NetBeans Release Schedule

2024年12月11日 星期三

Diagnosing the Error: Module javafx.fxml not found

在 NetBeans 使用 JavaFX 時,常遇到如下錯誤

  Error occurred during initialization of boot layer
  java.lang.module.FindException: Module javafx.fxml not found 

表示啟動層初始化時 Java 執行環境無法找到 javafx.fxml 模組。
這可能是由於 NetBeans 模組路徑的設定錯誤 或 根本未安裝模組所致。
以下為診斷和解決這個問題的步驟。

1.檢查 JavaFX SDK 安裝 及 NetBeans 設定正確否
   依據如下提示逐項檢查:
     how to set up NetBeans environment for JavaFX applications

2.打開 NetBeans 列印 Ant 腳本功能
   依據如下設定選項 
     Tools/Options/Java/Ant 或者 NetBeans/Settings...
        Ant Home: ...
        [v] Always Show Output

     Verbosity Level: Quiet/Normal/[Verbose]/Debug

    即可在執行 Run File 時,於 Output 視窗
    觀看Ant Target (build.xml) Output

3.檢查 NetBeans 執行 Ant run 腳本的參數填對否
   核對如下重要 java 執行參數
   run:
    Executing '/path/to/bin/java' with arguments:
    '-Dfile.encoding=UTF-8'
    
    '--add-modules'
    'javafx.controls,javafx.fxml,javafx.media'
    
    '-classpath'
    '/path/to/javafx-sdk-xx/lib/javafx-swt.jar:
     /path/to/javafx-sdk-xx/lib/javafx.base.jar:
     /path/to/javafx-sdk-xx/lib/javafx.controls.jar:
     /path/to/javafx-sdk-xx/lib/javafx.fxml.jar:
     /path/to/javafx-sdk-xx/lib/javafx.graphics.jar:
     /path/to/javafx-sdk-xx/lib/javafx.media.jar:
     /path/to/javafx-sdk-xx/lib/javafx.swing.jar:
     /path/to/javafx-sdk-xx/lib/javafx.web.jar:
     /path/to/MyProject/build/classes'
     
    '--module-path'
    '/path/to/MyProject/build/classes:
     /path/to/javafx-sdk-xx/lib/javafx-swt.jar:
     /path/to/javafx-sdk-xx/lib/javafx.base.jar:
     /path/to/javafx-sdk-xx/lib/javafx.controls.jar:
     /path/to/javafx-sdk-xx/lib/javafx.fxml.jar:
     /path/to/javafx-sdk-xx/lib/javafx.graphics.jar:
     /path/to/javafx-sdk-xx/lib/javafx.media.jar:
     /path/to/javafx-sdk-xx/lib/javafx.swing.jar:
     /path/to/javafx-sdk-xx/lib/javafx.web.jar'
     
    'MyJavaFXApp'

4.任何一處 Ant run 腳本的參數有缺,可對應到如下 NetBeans 設定有誤:
     Project Properties
       Libraries/
           Java Platform: JDK xx (Default)
           Compile/Compile-time Libraries:
               Classpath: JavaFX yy
           Run/Run-time Libraries:
               Modulepath: JavaFX yy

       Run/
           Configuration: <default config>
           VM Options:
               --add-modules javafx.controls,javafx.fxml,javafx.media
               
註1: 其實 Ant build 及 run 腳本的工作原理就是由 NetBeans 設定抽取相關參數,
    組合成如下命令列編譯及執行指令。故執行有問題可找回相關設定哪裏出問題。

    命令列編譯指令
    > javac -classpath "...\javafx-sdk-xx\lib\javafx.fxml.jar;...;." \
      MyJavaFXApp.java

    命令列執行指令
    > java --add-modules javafx.controls,javafx.fxml,javafx.media \
      -classpath . \
      --module-path "...\javafx-sdk-xx\lib\javafx.fxml.jar;..." \
      MyJavaFXApp

註2: NetBeans 執行 Ant run 腳本時,依序參考如下檔案
       MyProject/
         build.xml
         nbproject/
           build-impl.xml
           project.properties
     其中,project.properties有專案屬性如下,存放設定執行參數,亦可對照檢視設定錯誤原因。
       run.classpath=\
         ${javac.classpath}:\
         ${build.classes.dir}
       run.jvmargs=--add-modules javafx.controls,javafx.fxml,javafx.media
       run.modulepath=\
         ${javac.modulepath}:\
         ${libs.JavaFX_xx.classpath}

2024年12月10日 星期二

Two ways to draw shapes in JavaFX

 JavaFX 有 2 種畫形狀的寫法如下:

A. Pane容器放 Shape 形狀
  1.  
  2. import javafx.scene.layout.Pane;
  3. import javafx.scene.paint.Color;
  4. import javafx.scene.shape.Circle;
  5. import javafx.scene.shape.Rectangle;
  6.  
  7. ....
  8.  
  9. Pane pane = new Pane();
  10.  
  11. Circle circle = new Circle(50, 50, 30);
  12. circle.setFill(Color.BLUE);
  13.  
  14. Rectangle rectangle = new Rectangle(100, 100, 80, 40);
  15. rectangle.setFill(Color.RED);
  16.  
  17. pane.getChildren().addAll(circle, rectangle);
註1: Pane小孩清單會記住所有加入形狀元件,Pane大小調整後也會重新顯示所有形狀 註2: javafx.scene.shape支援形狀有 Circle, Rectangle, Ellipse, Line, Polygon, Polyline, Arc, CubicCurve, QuadCurve, Path 等 B. Canvas元件上畫出形狀
  1.  
  2. import javafx.scene.canvas.Canvas;
  3. import javafx.scene.canvas.GraphicsContext;
  4. import javafx.scene.paint.Color;
  5.  
  6. .....
  7.  
  8. Canvas canvas = new Canvas(300, 200);
  9. GraphicsContext gc = canvas.getGraphicsContext2D();
  10.  
  11. gc.setFill(Color.BLUE);
  12. gc.fillOval(50, 50, 60, 60); // Draw a circle
  13.  
  14. gc.setFill(Color.RED);
  15. gc.fillRect(150, 100, 80, 40); // Draw a rectangle
註1: javafx.scene.canvas.GraphicsContext會暫時記住所有畫圖區內容,直到大小異動才清空 註2: javafx.scene.canvas.GraphicsContext支援形狀有 // 矩形 fillRect(double x, double y, double w, double h) // 前景色填滿 strokeRect(double x, double y, double w, double h) // 前景色畫框 clearRect(double x, double y, double w, double h) // 背景色填滿 // 圓形 fillOval(double x, double y, double w, double h) strokeOval(double x, double y, double w, double h) // 弧形 fillArc(double x, double y, double w, double h, double startAngle, double arcExtent, ArcType closure) strokeArc(double x, double y, double w, double h, double startAngle, double arcExtent, ArcType closure) // 多邊形,多邊線 fillPolygon(double[] xPoints, double[] yPoints, int nPoints) strokePolygon(double[] xPoints, double[] yPoints, int nPoints) fillPolyline(double[] xPoints, double[] yPoints, int nPoints) strokePolyline(double[] xPoints, double[] yPoints, int nPoints) strokeLine(double x1, double y1, double x2, double y2) // 路徑模式, 一次只能維護一條路徑 beginPath() moveTo(double x, double y) lineTo(double x, double y) closePath() stroke() // 畫路徑框 fill() // 畫路徑內部