|
1 | | - |
2 | 1 | <!-- |
3 | 2 | { |
4 | | - "title": "Using Maven directly via CFML", |
| 3 | + "title": "Loading Java Libraries with Maven", |
5 | 4 | "id": "maven", |
6 | 5 | "categories": [ |
7 | 6 | "java" |
8 | 7 | ], |
9 | 8 | "since": "6.2", |
10 | | - "description": "How to use Maven in Lucee", |
| 9 | + "description": "Load Java libraries from Maven repositories - automatic dependency management for CFML applications.", |
11 | 10 | "keywords": [ |
12 | 11 | "Maven", |
13 | 12 | "Java", |
14 | | - "OSGi" |
| 13 | + "javaSettings", |
| 14 | + "dependencies" |
15 | 15 | ], |
16 | | - "related":[ |
| 16 | + "related": [ |
17 | 17 | "function-createobject", |
18 | | - "tag-import" |
| 18 | + "tag-import", |
| 19 | + "java-settings" |
19 | 20 | ] |
20 | 21 | } |
21 | 22 | --> |
22 | 23 |
|
23 | | -# Maven (Lucee 6.2) |
| 24 | +# Loading Java Libraries with Maven |
24 | 25 |
|
25 | | -Maven is a powerful tool for managing and retrieving Java libraries in modern applications. |
26 | | -It allows developers to easily integrate dependencies and manage project libraries. In Lucee 6.2, Maven integration has been added, providing more flexibility when using Java libraries within your CFML codebase. |
| 26 | +You want to use Apache POI to read Excel files. In the old days, you'd download the JAR, figure out its dependencies, put them all somewhere, and configure Lucee to find them. Maven handles this automatically - specify what you need and Lucee fetches everything. |
27 | 27 |
|
28 | | -## Why Maven? |
| 28 | +**Maven terms:** Libraries are identified by *groupId* (organization), *artifactId* (library name), and *version*. These combine into coordinates like `org.apache.poi:poi-ooxml:5.2.5`. |
29 | 29 |
|
30 | | -Maven is a widely-used framework that simplifies the management of Java dependencies. |
| 30 | +> **Common gotcha:** Using `import org.apache.poi...` alone doesn't load POI - it just shortcuts the class name. Without `javaSettings`, Lucee uses whatever's already on the classpath (often its bundled libraries). To load a specific version, you need both: `javaSettings` to fetch the library, `import` for convenience. |
31 | 31 |
|
32 | | -Lucee automatically handles the retrieval and inclusion of required libraries and their dependencies, reducing the manual work needed to manage them. |
| 32 | +## Quick Start |
33 | 33 |
|
34 | | -This makes integrating third-party Java libraries into your Lucee applications much easier and more efficient. |
| 34 | +```cfml |
| 35 | +component javaSettings='{"maven":["org.apache.poi:poi-ooxml:5.2.5"]}' { |
| 36 | + import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
| 37 | + import java.io.FileInputStream; |
35 | 38 |
|
36 | | -## How to Use Maven in Lucee |
| 39 | + function readFirstCell( path ) { |
| 40 | + var workbook = new XSSFWorkbook( new FileInputStream( arguments.path ) ); |
| 41 | + var sheet = workbook.getSheetAt( 0 ); |
| 42 | + return sheet.getRow( 0 ).getCell( 0 ).getStringCellValue(); |
| 43 | + } |
| 44 | +} |
| 45 | +``` |
37 | 46 |
|
38 | | -Lucee has supported the `this.javasettings` setting in the `Application.cfc` for a while. |
39 | | -This allows developers to define directories containing Java classes or `.jar` files. Starting from Lucee 6.2, this functionality has been extended to support Maven libraries. |
40 | | -You can now define Maven dependencies in the configuration file `.CFConfig.json`, within your `Application.cfc`, or directly in your CFML components. |
| 47 | +Lucee downloads POI and all its dependencies automatically. |
41 | 48 |
|
42 | | -Lucee uses these configurations to load Java classes in a structured manner, ensuring that dependencies are managed effectively. |
| 49 | +## Where to Define Dependencies |
43 | 50 |
|
44 | | -## Lucee Config (`.CFConfig.json`) |
| 51 | +| Scope | Use Case | |
| 52 | +|-------|----------| |
| 53 | +| **Component attribute** | Isolate dependencies to a single component | |
| 54 | +| **Application.cfc** | Share across your application | |
| 55 | +| **`.CFConfig.json`** | Server-wide defaults | |
| 56 | +| **createObject()** | One-off dynamic loading | |
45 | 57 |
|
46 | | -In `.CFConfig.json`, you can define Maven dependencies that will be used globally by your Lucee server for loading Java classes. |
| 58 | +### Component (recommended for isolation) |
47 | 59 |
|
48 | | -```json |
49 | | -{ |
50 | | - "javasettings": { |
51 | | - "maven": [ |
52 | | - { |
53 | | - "groupId": "org.quartz-scheduler", |
54 | | - "artifactId": "quartz", |
55 | | - "version": "2.3.2" |
56 | | - }, |
57 | | - { |
58 | | - "groupId": "org.quartz-scheduler", |
59 | | - "artifactId": "quartz-jobs", |
60 | | - "version": "2.3.2" |
61 | | - } |
62 | | - ] |
63 | | - } |
| 60 | +Each component can have its own dependencies - different components can even use different versions of the same library without conflicts: |
| 61 | + |
| 62 | +```cfml |
| 63 | +component javaSettings='{"maven":["org.apache.poi:poi-ooxml:5.2.5"]}' { |
| 64 | + // POI 5.2.5 available here |
64 | 65 | } |
65 | 66 | ``` |
66 | 67 |
|
67 | | -The `version` attribute is optional. If not specified, Lucee will automatically fetch the latest version available for the specified Maven artifact. |
| 68 | +### Application.cfc |
| 69 | + |
| 70 | +Share dependencies across your entire application: |
| 71 | + |
| 72 | +```cfml |
| 73 | +// Application.cfc |
| 74 | +this.javaSettings = { |
| 75 | + "maven": [ |
| 76 | + "org.apache.poi:poi-ooxml:5.2.5", |
| 77 | + "com.google.guava:guava:32.1.3-jre" |
| 78 | + ] |
| 79 | +}; |
| 80 | +``` |
68 | 81 |
|
69 | | -In addition, we also support the more concise Gradle style. |
| 82 | +### .CFConfig.json (server-wide) |
70 | 83 |
|
71 | 84 | ```json |
72 | 85 | { |
73 | | - "javasettings": { |
74 | | - "maven": [ |
75 | | - "org.graalvm.polyglot:polyglot:24.1.1" |
76 | | - , "org.graalvm.polyglot:python:24.1.1" |
77 | | - ] |
78 | | - } |
| 86 | + "javaSettings": { |
| 87 | + "maven": [ |
| 88 | + "org.quartz-scheduler:quartz:2.3.2", |
| 89 | + "org.quartz-scheduler:quartz-jobs:2.3.2" |
| 90 | + ] |
| 91 | + } |
79 | 92 | } |
80 | 93 | ``` |
81 | 94 |
|
82 | | -## Application.cfc |
| 95 | +### createObject() (dynamic) |
83 | 96 |
|
84 | | -In your `Application.cfc`, you can override or extend the global Java settings by adding Maven dependencies specific to your application. |
| 97 | +Load dependencies at runtime for one-off usage: |
85 | 98 |
|
86 | | -```javascript |
87 | | -this.javasettings = { |
88 | | - "maven": [ |
89 | | - { |
90 | | - "groupid": "commons-beanutils", |
91 | | - "artifactid": "commons-beanutils", |
92 | | - "version": "1.9.4" |
93 | | - } |
94 | | - ] |
95 | | -}; |
| 99 | +```cfml |
| 100 | +BeanUtils = createObject( "java", "org.apache.commons.beanutils.BeanUtils", { |
| 101 | + "maven": [ "commons-beanutils:commons-beanutils:1.9.4" ] |
| 102 | +}); |
96 | 103 | ``` |
97 | 104 |
|
98 | | -This allows you to tailor the Java dependencies for your application, providing more flexibility in how libraries are loaded and used. |
| 105 | +## Dependency Syntax |
99 | 106 |
|
100 | | -## Defining Maven Dependencies in a Component |
| 107 | +### Shorthand (recommended) |
101 | 108 |
|
102 | | -You can also define Maven dependencies as part of a component, ensuring that only the classes loaded within that component will use the specified libraries. |
| 109 | +``` |
| 110 | +"groupId:artifactId:version" |
| 111 | +``` |
103 | 112 |
|
104 | | -```javascript |
105 | | -component javaSettings = '{ |
106 | | - "maven": [ |
107 | | - { |
108 | | - "groupid": "commons-beanutils", |
109 | | - "artifactid": "commons-beanutils", |
110 | | - "version": "1.9.4" |
111 | | - } |
112 | | - ] |
113 | | -}' { |
| 113 | +Examples: |
114 | 114 |
|
115 | | -} |
| 115 | +```cfml |
| 116 | +"org.apache.poi:poi-ooxml:5.2.5" |
| 117 | +"com.google.guava:guava:32.1.3-jre" |
116 | 118 | ``` |
117 | 119 |
|
118 | | -This encapsulation is highly beneficial because it isolates a component from the rest of the environment, allowing it to use different versions of the same libraries without causing conflicts. This ensures that you can integrate components seamlessly without worrying about library version clashes. |
| 120 | +### Verbose (when you need more control) |
119 | 121 |
|
120 | | -## Using Maven with `CreateObject` |
| 122 | +```json |
| 123 | +{ |
| 124 | + "groupId": "org.apache.poi", |
| 125 | + "artifactId": "poi-ooxml", |
| 126 | + "version": "5.2.5" |
| 127 | +} |
| 128 | +``` |
121 | 129 |
|
122 | | -You can also define Maven dependencies directly when creating a Java object using the `CreateObject` function. |
| 130 | +### Version is Optional |
123 | 131 |
|
124 | | -```javascript |
125 | | -createObject("java", "org.apache.commons.beanutils.BeanUtils", { |
126 | | - "maven": [ |
127 | | - { |
128 | | - "groupid": "commons-beanutils", |
129 | | - "artifactid": "commons-beanutils", |
130 | | - "version": "1.9.4" |
131 | | - } |
132 | | - ] |
133 | | -}); |
134 | | -``` |
| 132 | +Omit version to fetch the latest available: |
135 | 133 |
|
136 | | -This method provides even more flexibility, allowing you to load Java classes and libraries dynamically at runtime. |
| 134 | +```cfml |
| 135 | +"org.apache.poi:poi-ooxml" // gets latest version |
| 136 | +``` |
137 | 137 |
|
138 | | -## Security |
| 138 | +## Security: Checksum Validation |
139 | 139 |
|
140 | | -Lucee validates downloaded Maven artifacts against checksums to ensure integrity through dual validation: |
| 140 | +Lucee validates downloads against Maven repository checksums. For extra security, specify your own. |
141 | 141 |
|
142 | | -Against Maven repository checksums |
143 | | -Against user-defined checksums (if provided) |
| 142 | +Full shorthand syntax: `groupId:artifactId:version:scope:transitive:checksum` |
144 | 143 |
|
145 | | -Define checksums in .CFConfig.json: |
| 144 | +```cfml |
| 145 | +// With checksum (scope=compile, transitive=false) |
| 146 | +"commons-beanutils:commons-beanutils:1.9.4:compile:false:sha1-d52b9abcd97f38c81342bb7e7ae1eee9b73cba51" |
146 | 147 |
|
147 | | -```json |
| 148 | +// Verbose |
148 | 149 | { |
149 | | - "javasettings": { |
150 | | - "maven": [ |
151 | | - { |
152 | | - "groupId": "org.example", |
153 | | - "artifactId": "mylib", |
154 | | - "version": "1.0.0", |
155 | | - "checksum": "sha1-d52b9abcd97f38c81342bb7e7ae1eee9b73cba51" |
156 | | - } |
157 | | - ] |
158 | | - } |
| 150 | + "groupId": "commons-beanutils", |
| 151 | + "artifactId": "commons-beanutils", |
| 152 | + "version": "1.9.4", |
| 153 | + "checksum": "sha1-d52b9abcd97f38c81342bb7e7ae1eee9b73cba51" |
159 | 154 | } |
160 | 155 | ``` |
161 | 156 |
|
162 | | -Or using Gradle style: |
| 157 | +Supported algorithms: MD5, SHA-1, SHA-256, SHA-512. Failed validation prevents installation. |
163 | 158 |
|
164 | | -``` |
165 | | -"commons-beanutils:commons-beanutils:1.9.4:compile:false:sha1-d52b9abcd97f38c81342bb7e7ae1eee9b73cba51" |
166 | | -``` |
| 159 | +## Finding Maven Coordinates |
167 | 160 |
|
168 | | -Supported algorithms: MD5, SHA-1, SHA-256, SHA-512 |
169 | | -If no checksum is specified, Lucee uses the default from the Maven repository. Failed checksum validations prevent dependency installation. |
| 161 | +Search [Maven Central](https://search.maven.org/) for the library you need. The coordinates are shown on the artifact page - just copy them. |
170 | 162 |
|
171 | | -## Classloader Recycling |
| 163 | +## Classloader Reuse |
172 | 164 |
|
173 | | -Lucee automatically generates a unique hash based on the defined Java settings and maintains a pool of corresponding classloaders. This means that classloaders are reused efficiently, minimizing resource consumption and avoiding the overhead of creating new classloaders unnecessarily. |
| 165 | +Lucee hashes your javaSettings and reuses classloaders with matching configurations. This means: |
174 | 166 |
|
175 | | -## Limitations |
| 167 | +- Multiple components with identical dependencies share one classloader |
| 168 | +- No overhead from creating duplicate classloaders |
| 169 | +- Memory stays efficient even with many components using Maven |
176 | 170 |
|
177 | | -- Maven libraries are downloaded at runtime, meaning you must ensure the necessary dependencies are available during the build phase. This can be handled in `Server.cfc->onBuild`, especially in Docker environments where the image is built beforehand. |
178 | | -- Currently, this feature is only supported in CFML. You cannot use it in Java-based extensions for Lucee, but future updates are planned to extend this functionality to Java code as well. |
| 171 | +## Limitations |
179 | 172 |
|
180 | | -By integrating Maven support into Lucee, managing Java libraries becomes much more efficient and less error-prone. This feature ensures that dependencies are handled properly across different parts of your application, reducing potential conflicts and simplifying development. |
| 173 | +- **Runtime download** - Libraries are fetched when first needed. For Docker, pre-download in `Server.cfc->onBuild` |
| 174 | +- **CFML only** - Can't use this in Java-based Lucee extensions (yet) |
0 commit comments