EE-mode
Since Ceylon 1.3.1 the JVM compiler has had a special "EE-mode" to ease interoperability with Java-EE-like environments where classes are instantiated and manipulated by frameworks.
final
method modifier
Normally the ceylon compiler wil generate final
methods for elements which subclasses should
not be able to override. This makes it safer to subclass a Ceylon class in Java.
In EE mode, classes are generated without having the final
modifier on their methods.
The rationale for this is to make these classes proxiable by runtime bytecode generation.
public
nullary constructor
Normally the Ceylon compiler will generate a nullary constructor because
Ceylon classes are implicitly java.io.Serializable
,
and so must have a non-private
nullary constructor.
In EE mode, this constructor is made public
.
The rationale for this is to make classes usable with JAX-RS.
late
initialization checking
Normally the Ceylon compiler will add runtime checks to the getters and setters for late
attributes to prevent those attributes from being used before they've been initialized,
or to prevent them from being reinitialized if they're not variable
.
In many cases this runtime check can simply use the null-ness of the underlying field to
detect access before initialization, or reinitialization. In other cases, specifically
when the attribute gets transformed into a primitive-typed field, or the attribute has a nullable type,
it is necessary to use an extra boolean
field to track the initialization of the attribute's field.
In EE mode the compiler omits runtime initialization checks which would require an
extra boolean
field.
The rationale for this is that frameworks will inject the attribute directly into the field (not via the setter), and don't know about the boolean state tracking field, meaning that without EE-mode a Ceylon class would incorrectly throw an initialization exception.
Java types for "optional primitive" fields
Normally the Ceylon compiler will tranform an attribute of type Integer
to a long
field, and an attribute of type
Integer?
to a field of type ceylon.language.Integer
(which, being a reference type, can be null). Similarly Ceylon
boxes are also used for String?
, Float?
, Character?
, Boolean?
and Byte?
(see type mapping for details).
In EE mode such fields are of the equivalent Java boxed primitive types
java.lang.Long
, java.lang.String
, java.lang.Double
, java.lang.Character
,
java.lang.Boolean
and java.lang.Byte
respectively.
The rationale for this is that frameworks injecting field state typcially understand these types without needing special adapter classes to be written.
Java types for List
, Set
and Map
Normally the Ceylon compiler will transform an attribute of type ceylon.language::List<Element>
to a field of that type. Likewise ceylon.language::Set<Element>
and ceylon.language::Map<Key,Item>
.
In EE mode such fields are of type java.util.List
, java.util.Set
and java.util.Map
respectively.
The compiler wraps a Ceylon collection in an adapter on set and unwraps, or rewraps on get.
Such wrapping and rewrapping applies to arbitrary nesting of these collections, so long as the
static types are ceylon.language::List<Element>
, ceylon.language::Set<Element>
or ceylon.language::Map<Key,Item>
.
Moreover an attribute of static type ceylon.language::List<Integer>
is stored in a field of type
java.util.List<java.lang.Long>
, and likewise for the other "primitive" types and the other
collections.
For example:
class Example() {
shared late List<Integer> list; // java.util.List<java.lang.Long>
shared late Map<String, List<String>> map; // java.util.Map<java.lang.String, java.util.List<java.lang.String>>
shared late MutableSet<String> set; // EE-mode mapping does not apply, because the static type is not Set
}
The rationale for this is that frameworks injecting field state typcially understand these types without needing special adapter classes to be written.
Activating EE mode
EE mode is activated for all classes in a module when javax.javaeeapi
or equivalently maven:javax:"javaee-api"
(any version) is imported in the module.ceylon
.
EE mode is also activated for a class when that class is annotated with any of the following:
javax.xml.bind.annotation.XmlAccessorType
javax.persistence.Entity
-
javax.persistence.Embeddable
(since Ceylon 1.3.2) javax.inject.Inject
javax.ejb.Stateless
javax.ejb.Stateful
javax.ejb.MessageDriven
javax.ejb.Singleton
If necessary, the compiler options
--ee-annotation
and
--ee-import
can be used to replace
the fully qualified annotation type names and module names which trigger activation.
Alternatively the option
--ee
can be used to enable EE mode for the entire compilation.
These options can also be specified in your
.ceylon/config
file, for example
[compiler.jvm]
eeimport=mvn:"org.springframework.boot:spring-boot"
eeannotation=org.springframework.beans.factory.annotation.Autowired