Skip to content

Commit ce87bc0

Browse files
committed
update java recipes to be cfml dev orientated
1 parent 29f8d0e commit ce87bc0

File tree

4 files changed

+101
-152
lines changed

4 files changed

+101
-152
lines changed

docs/recipes/component-getclass-method.md

Lines changed: 21 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@
22
{
33
"title": "getClass() Method for Components",
44
"id": "component-getclass-method",
5-
"description": "This document explains the getClass() method for CFML components that implement Java interfaces, enabling seamless Java interoperability.",
5+
"since": "7.0",
6+
"description": "Get the Java class of a component that implements a Java interface.",
67
"keywords": [
78
"getClass",
89
"component",
910
"java",
10-
"proxy",
11-
"interface",
12-
"interoperability"
11+
"interface"
1312
],
1413
"related": [
1514
"tag-component",
16-
"function-createdynamicproxy",
17-
"new-operator",
18-
"developing-with-lucee-server"
15+
"function-createdynamicproxy"
1916
],
2017
"categories": [
21-
"core",
2218
"component",
2319
"java"
2420
]
@@ -27,49 +23,38 @@
2723

2824
# getClass() Method for Components
2925

30-
In Lucee, components that implement Java interfaces can use the `getClass()` method to obtain the Java class representation.
26+
When a component implements a Java interface, you can call `getClass()` to get the underlying Java class. Useful when Java code needs to inspect your component's type.
3127

32-
This method automatically creates (if needed) a dynamic proxy and returns the proxy's class, enabling seamless Java interoperability without explicit proxy creation.
28+
**Java terms:** A *proxy* is a wrapper object that Lucee creates to make your component look like a real Java class. *Reflection* is when Java code inspects objects at runtime to discover their methods and properties - many frameworks use this for dependency injection, serialization, and type checking.
3329

34-
*Available since Lucee 7.0*
35-
36-
## Basic Usage
37-
38-
When called on a component that implements Java interfaces, `getClass()` returns the Java class of the dynamic proxy:
30+
## Usage
3931

4032
```lucee
41-
mymap = new component implements="java:java.util.Map" {
42-
// component implementation
33+
myMap = new component implements="java:java.util.Map" {
34+
// implement Map methods...
4335
};
4436
45-
classInfo = mymap.getClass(); // Returns proxy class
46-
dump(classInfo);
37+
// Get the Java class
38+
cls = myMap.getClass();
39+
dump( cls.getName() ); // something like "lucee.runtime.proxy.Map$..."
4740
```
4841

49-
This is equivalent to the more verbose:
42+
This is shorthand for:
5043

5144
```lucee
52-
classInfo = createDynamicProxy(mymap).getClass();
45+
cls = createDynamicProxy( myMap ).getClass();
5346
```
5447

55-
## Method Resolution Order
48+
## Resolution Order
5649

57-
The `getClass()` method follows a specific resolution order:
58-
59-
1. **Custom Function**: If the component defines a function named "getClass", that function is called
60-
2. **Property Getter**: If the component has a property named "class" with `accessor=true`, the getter is used
61-
3. **Default Behavior**: Otherwise, a dynamic proxy is created and `proxy.getClass()` is returned
50+
1. If the component has a `getClass()` function, that's called
51+
2. If the component has a `class` property with accessors, the getter is used
52+
3. Otherwise, returns the Java proxy class
6253

6354
## Requirements
6455

65-
- The component must implement at least one Java interface
66-
- The method only applies to components, not regular objects
67-
68-
## Use Cases
56+
The component must implement at least one Java interface using `implements="java:..."` syntax.
6957

70-
This feature is particularly useful for:
58+
## When You'd Use This
7159

72-
- Java library integration where class information is needed
73-
- Reflection operations on component proxies
74-
- Framework development requiring class metadata
75-
- Simplified Java interoperability code
60+
Some Java libraries inspect the class of objects you pass them - to check types, discover methods, or register handlers. Without `getClass()`, you'd need to manually create a proxy first. This makes it seamless.
Lines changed: 47 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<!--
22
{
3-
"title": "Convert a CFML Function/Component to use in Java",
3+
"title": "Using CFML Functions and Components in Java",
44
"id": "convert-a-cfml-func-to-java",
5-
"description": "Learn how to convert user-defined functions or components in Lucee to use them in Java. This guide demonstrates how to define components to implement Java interfaces, pass components to Java methods, explicitly define interfaces, and use the onMissingMethod feature. It also shows how to convert user-defined functions to Java lambdas.",
5+
"description": "Pass CFML components and functions to Java code - implement Java interfaces with CFCs, use functions as Java lambdas.",
66
"since": "6.0",
77
"keywords": [
88
"conversion",
@@ -13,74 +13,81 @@
1313
"lambda",
1414
"Lucee"
1515
],
16-
"categories":[
16+
"categories": [
1717
"java"
1818
],
1919
"related": [
20-
"tag-component"
20+
"tag-component",
21+
"dynamic-proxy-enhancements",
22+
"java-explicit-casting"
2123
]
2224
}
2325
-->
2426

25-
# Convert a CFML Function/Component to use in Java
27+
# Using CFML Functions and Components in Java
2628

27-
Lucee allows you to convert user-defined functions or components so you can use them in Java.
29+
Many Java libraries accept objects that implement specific *interfaces* - contracts defining what methods an object must have. Lucee lets you pass CFML components and functions directly to Java code.
2830

29-
## Component to Java Class
31+
**Java terms:** A *Java interface* defines method signatures a class must implement (like a blueprint). A *lambda* is a shorthand for a single-method interface - Java 8+ uses these heavily for callbacks and streaming APIs.
3032

31-
You simply add all functions defined for a Java interface to a component like this:
33+
## Component to Java Interface
34+
35+
Implement the interface's methods in your component:
3236

3337
```lucee
34-
// Component that implements all methods from interface CharSequence
38+
// MyString.cfc - implements CharSequence interface
3539
component {
36-
function init(String str) {
37-
variables.str = reverse(arguments.str);
38-
}
39-
function length() {
40-
SystemOutput("MyString.length:" & str.length(), 1, 1);
41-
return str.length();
42-
}
43-
// ... more functions here
40+
function init( String str ) {
41+
variables.str = reverse( arguments.str );
42+
}
43+
44+
function length() {
45+
return str.length();
46+
}
47+
48+
// ... implement other CharSequence methods
4449
}
4550
```
4651

47-
### Pass to Java
48-
49-
Then you can pass that component to a Java method needing a specific interface/class.
52+
Then pass it to Java methods expecting that interface:
5053

5154
```lucee
52-
// This class has a method that takes as an argument a CharSequence.
53-
// This way we can force Lucee to convert/wrap our component to that interface.
54-
HashUtil = createObject("java", "lucee.commons.digest.HashUtil");
55+
HashUtil = createObject( "java", "lucee.commons.digest.HashUtil" );
56+
cfc = new MyString( "Susi Sorglos" );
5557
56-
// This component implements all necessary functions for the CharSequence
57-
cfc = new MyString("Susi Sorglos");
58-
59-
// Calling the method HashUtil.create64BitHashAsString(CharSequence cs) with our component as an argument
60-
hash = HashUtil.create64BitHashAsString(cfc);
61-
dump(hash);
58+
// HashUtil.create64BitHashAsString() expects CharSequence - Lucee converts automatically
59+
hash = HashUtil.create64BitHashAsString( cfc );
60+
dump( hash );
6261
```
6362

64-
### Explicit Definition and "onMissingMethod"
63+
### Using implementsJava and onMissingMethod
6564

66-
Of course, you can also define the interface you want to implement explicitly and you can use “onMissingMethod” so you do not have to implement every single function separately.
65+
Declare the interface explicitly and handle method calls dynamically:
6766

6867
```lucee
6968
component implementsJava="java.util.List" {
70-
function onMissingMethod(name, args) {
71-
if (name == "size") return 10;
72-
throw "method #name# is not supported!";
73-
}
69+
function onMissingMethod( name, args ) {
70+
if ( name == "size" ) return 10;
71+
throw "method #name# is not supported!";
72+
}
7473
}
7574
```
7675

77-
## User-Defined Function to Java (as Lambda)
76+
See [[java-explicit-casting]] for when you need to cast components to specific interfaces.
77+
78+
## Functions as Java Lambdas
7879

79-
Functions get converted to a Lambda interface when the interface matches automatically. You can do the same with regular functions, but here the conversion happens when passing to Java.
80+
When a Java method expects a *functional interface* (an interface with one method), you can pass a CFML function directly. Lucee converts it automatically:
8081

8182
```lucee
82-
numeric function echoInt(numeric i) {
83-
if (i == 1) throw "Test output!!!";
84-
return i * 2;
83+
numeric function doubleIt( numeric i ) {
84+
return i * 2;
8585
}
86+
87+
// Java's IntStream.map() expects IntUnaryOperator (one method: int applyAsInt(int))
88+
import java.util.stream.IntStream;
89+
result = IntStream::of( 1, 2, 3 ).map( doubleIt ).sum();
90+
dump( result ); // 12 (2 + 4 + 6)
8691
```
92+
93+
See [[java-in-functions-and-closures]] for more on Java lambdas and the `type="java"` function attribute.
Lines changed: 32 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
<!--
22
{
3-
"title": "Dynamic Proxy Enhancements in Lucee 7",
3+
"title": "Dynamic Proxy Enhancements",
44
"id": "dynamic-proxy-enhancements",
5-
"description": "Learn about the improvements to dynamic proxy creation in Lucee 7, including automatic inclusion of component functions and properties when implementing Java interfaces.",
5+
"since": "7.0",
6+
"description": "Lucee 7 improvements to dynamic proxy creation - all component functions and properties are now always included when implementing Java interfaces.",
67
"keywords": [
78
"dynamic proxy",
89
"java",
@@ -24,129 +25,85 @@
2425
}
2526
-->
2627

27-
# Dynamic Proxy Enhancements in Lucee 7
28+
# Dynamic Proxy Enhancements
2829

29-
All component functions and properties are now always included in dynamic proxies, making Java interoperability more predictable.
30+
When you pass a CFML component to Java code, Lucee creates a *proxy* - a wrapper that makes your component look like a Java object. In Lucee 7, proxies now include **all** your component's functions and properties, not just the interface methods.
3031

31-
## What Changed in Lucee 7
32+
**Java terms:** A *Java interface* is a contract defining method signatures a class must implement (like CFML's `implements` attribute). A *proxy* wraps your component so Java sees it as implementing that interface.
3233

33-
### Component Functions and Properties Always Included
34+
## What Changed
3435

35-
In previous versions, when creating a dynamic proxy from a component that implements Java interfaces, not all component functions and properties were consistently included in the proxy. Lucee 7 ensures that **all component functions and properties are always included** in the dynamic proxy.
36+
Previously, custom methods you added beyond the interface weren't consistently available through the proxy. Now they always are (LDEV-5421).
3637

37-
This enhancement (LDEV-5421) makes dynamic proxies behave more predictably and eliminates subtle issues where component methods might not be accessible through the proxy.
38-
39-
## Basic Usage
40-
41-
When you create a component that implements a Java interface, you can use `createDynamicProxy()` to get a Java proxy object:
38+
## Example
4239

4340
```cfml
44-
// Define a component implementing java.util.Map
4541
myComponent = new component implements="java:java.util.Map" {
46-
47-
function size(){
48-
return 42;
49-
}
50-
51-
function isEmpty(){
52-
return false;
53-
}
42+
function size() { return 42; }
43+
function isEmpty() { return false; }
44+
function get( key ) { return "value"; }
45+
function put( key, value ) { return null; }
46+
// ... other Map methods
5447
5548
// Custom function (not part of Map interface)
56-
function customMethod(){
57-
return "This is now always included in the proxy!";
58-
}
59-
60-
// Additional required Map methods...
61-
function get( key ){
62-
return "value";
49+
function customMethod() {
50+
return "Now always included in the proxy!";
6351
}
64-
65-
function put( key, value ){
66-
return null;
67-
}
68-
69-
// ... other Map interface methods
7052
};
7153
72-
// Create the dynamic proxy
7354
proxy = createDynamicProxy( myComponent, [ "java.util.Map" ] );
7455
75-
// All component methods are accessible through the proxy
76-
systemOutput( proxy.size() ); // 42
77-
systemOutput( proxy.customMethod() ); // Works in Lucee 7!
56+
systemOutput( proxy.size() ); // 42
57+
systemOutput( proxy.customMethod() ); // Works in Lucee 7!
7858
```
7959

80-
## Automatic Proxy Creation with getClass()
60+
## getClass() Shorthand
8161

82-
Lucee 7 also introduces the ability to call `.getClass()` directly on components that implement Java interfaces, automatically creating a dynamic proxy if needed:
62+
Components with `implements="java:..."` can call `.getClass()` directly - Lucee creates the proxy automatically:
8363

8464
```cfml
8565
myComponent = new component implements="java:java.util.Map" {
86-
function size(){
87-
return 42;
88-
}
89-
// ... other methods
66+
// ... methods
9067
};
9168
92-
// New in Lucee 7 - automatic proxy creation
9369
classInfo = myComponent.getClass();
9470
95-
// Previously required explicit proxy creation:
71+
// Equivalent to:
9672
// classInfo = createDynamicProxy( myComponent, [ "java.util.Map" ] ).getClass();
9773
```
9874

99-
See [[component-getclass-method]] for more details on this feature.
100-
101-
## Use Cases
75+
See [[component-getclass-method]] for details.
10276

103-
These enhancements are particularly valuable when:
77+
## Runnable Example
10478

105-
- **Building Java library integrations** - Your component methods are reliably accessible through the proxy
106-
- **Extending Java interfaces** - Add custom functionality beyond the interface contract
107-
- **Framework development** - Create components that implement Java interfaces with additional CFML-specific methods
108-
- **Working with callbacks** - Pass components to Java libraries that expect interface implementations
109-
110-
## Example: Implementing java.lang.Runnable
79+
A practical use case - implementing Java's `Runnable` interface to run code in a thread:
11180

11281
```cfml
113-
// Create a component implementing Runnable
11482
task = new component implements="java:java.lang.Runnable" {
115-
11683
variables.executionCount = 0;
11784
118-
function run(){
85+
function run() {
11986
variables.executionCount++;
12087
systemOutput( "Task executed ##variables.executionCount## times" );
12188
}
12289
123-
// Custom method to check execution count
124-
function getExecutionCount(){
90+
// Custom method - now accessible through proxy
91+
function getExecutionCount() {
12592
return variables.executionCount;
12693
}
12794
};
12895
129-
// Create proxy and pass to Java's ExecutorService
13096
proxy = createDynamicProxy( task, [ "java.lang.Runnable" ] );
13197
132-
// Create a Java thread
13398
thread = createObject( "java", "java.lang.Thread" ).init( proxy );
13499
thread.start();
135100
thread.join();
136101
137-
// Access custom methods through the original component
138102
systemOutput( "Total executions: " & task.getExecutionCount() );
139103
```
140104

141-
## Key Benefits
142-
143-
1. **Predictable behavior** - All component methods are consistently available through the proxy
144-
2. **Simplified code** - Automatic proxy creation with `.getClass()`
145-
3. **Better Java integration** - Seamlessly mix CFML and Java functionality
146-
4. **Enhanced flexibility** - Add custom methods beyond interface requirements
147-
148-
## See Also
105+
## When You'd Use This
149106

150-
- [[component-getclass-method]] - Using getClass() for automatic proxy creation
151-
- [[java-class-interaction]] - General Java interoperability in Lucee
152-
- [[function-createdynamicproxy]] - createDynamicProxy() function reference
107+
- **Java library callbacks** - pass components to Java code expecting interface implementations
108+
- **Custom methods on proxies** - add CFML-specific helpers alongside interface methods
109+
- **Threading** - implement Runnable, Callable, or other Java concurrency interfaces

0 commit comments

Comments
 (0)