You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
State.Group.remove(State) added, allowing a state to leave a group; DefaultStateGroup now removes the associated listener so a removed state no longer participates or is retained.
DefaultStateGroup.disableOthers() now snapshots the member list before traversing it. Deactivating a member notifies its listeners synchronously, one of which may leave the group, a panel made undisplayable doing exactly that, corrupting the traversal.
is.codion.common.rmi
ServerConfiguration.builder() no longer takes port parameters, the server and registry ports are now builder methods defaulting to SERVER_PORT and REGISTRY_PORT respectively.
ServerConfiguration.Builder.build() now rejects a negative server port with a clear message instead of deferring to an obscure RMI error, catching a missing SERVER_PORT configuration early.
Clients.SERVER_HOSTNAME configuration key renamed from codion.server.hostname to codion.client.hostname, it is a client-side setting and now sits under codion.client.* consistent with codion.client.http.hostname.
ServerAdmin.getConnectionLimit()/setConnectionLimit() renamed to connectionLimit()/connectionLimit(int), de-beanified to the house name()/name(value) style. AbstractServer follows suit, along with getMaintenanceInterval()/setMaintenanceInterval(); the protected getAdmin()/setAdmin() are left as-is to avoid clashing with the admin(User) authentication method.
AbstractServer.disconnect() now removes and closes the client connection while holding the connections monitor, a client reconnecting while maintenance disconnects it can no longer be handed a just-closed connection.
AbstractServer.shutdown() now flips the shuttingDown flag atomically and snapshots the connections under the monitor, and connect() re-checks the flag within the monitor, so a connection created during shutdown can no longer escape the disconnect sweep.
AbstractServer.startAuxiliaryServers() now shuts down the single-thread executor used to name the starting thread, it previously abandoned one idle thread per auxiliary server.
SerializationFilterFactory, a blank line in a serialization pattern file no longer joins into an empty pattern element, which ObjectInputFilter rejects, bricking server startup. Lines are now trimmed and blank lines skipped.
AbstractServer.unexportSilently() now logs an already unexported object at debug rather than error.
ServerConfiguration.rmi(boolean) added, default true; when false the server does no RMI wiring at all. AbstractServer no longer extends UnicastRemoteObject, it exports itself explicitly and only when RMI is enabled or the admin interface is (adminPort > 0, which the EntityServerMonitor reaches through the registry-bound server). A pure-HTTP server, rmi(false) with no admin, exports nothing, creates no registry and refuses a remote connect() while still serving its auxiliary (HTTP) servers in process, removing the RMI attack surface a HTTP/JSON-only deployment never used. build() now requires a server port only when the server is exported (RMI or admin), not unconditionally.
is.codion.common.db
ConnectionPoolWrapper get/set/is accessors (cleanupInterval, idleTimeout, minimumPoolSize, maximumPoolSize, maximumCheckOutTime, collectSnapshotStatistics, collectCheckOutTimes) de-beanified to the house name()/name(value) style, consistent with the interface's own user()/statistics() methods. The JMX metric MXBeans retain bean naming, as required by the JMX attribute contract.
ReferentialIntegrityException(String, Operation), UniqueConstraintException(String) and QueryTimeoutException(String) added, for a client reconstructing these from a message, having no SQLException to hand.
ReportType no longer specifies the type of the loaded report object, which was never bound to anything but Object or a wildcard at any use site, being an implementation detail of the Report the type is registered with. It required every domain naming a report to depend on the reporting engine, JasperReports demanding java.desktop of an Android or headless client which need never deserialize a JasperPrint.
is.codion.common.model
DefaultFilterModelItems, the selection is now preserved by item across item insertion and removal. IncludedItems.add(int, ..), IncludedItems.remove(int), IncludedItems.remove(int, int) and Items.remove(item/items/predicate) shift the indexes of the items at and after the mutation point, but left the selected indexes untouched, so the selection ended up pointing at the wrong items. Preserving by item is idempotent with respect to a view which shifts the indexes on its own, such as a JTable, so no selection is adjusted twice.
DefaultMultiSelection, the index(), indexes(), item() and items() facades now notify only when their own value actually changes, honoring the Notify.CHANGED contract and matching DefaultListSelection. Ending an adjustment via adjusting(false) previously notified all four unconditionally, bypassing the no-op guard in applyTarget().
MultiSelection.adjusting() added, a getter for the existing setter, so code which may run inside a group of its caller's making can save and restore the state rather than terminate the group.
DefaultFilterModelItems saves and restores the adjusting state around its own grouping, an items mutation performed inside a caller's group no longer ends it early.
FilterModel.IncludedItems.get() and FilteredItems.get() now return a stable snapshot rather than an unmodifiable live view over the model's backing list. The view reflected an in-place mutation, set() clearing and repopulating the list, and a caller iterating it while another thread refreshed, an Android or web client doing exactly that, raced the mutation. The top-level Items.get() already copied; the two are now consistent. The Swing table reads rows by index, get(int)/size(), so the copy adds nothing to its hot path.
DefaultFilterComboBoxModel, its own IncludedItems.get() and FilteredItems.get() likewise return a stable snapshot now, and the defensive copies their notifyChanges() published, workarounds for the live view, are removed.
is.codion.framework.i18n
FrameworkMessages.save() removed, some minor mnemonic improvements.
is.codion.framework.domain
DerivedValue.from() javadoc now states that a derived value provider must be total, every cached derived value being computed when an entity is made immutable, not only the ones a caller reads.
Domain.report(ReportType) now returns Report and Domain.reports() a Map, Report>, following ReportType.
Domain.domains() now returns one Domain per DomainType, resolving multiple implementations of one type to the most derived, the unique class every other implementation class is assignable from, a variant extending the base such as one adding engine backed reports. It replaces the previous first-service-loaded-wins, which was classpath-order dependent and forced the two registrations of such a pair off shared classpaths. Identical implementations, a jar present twice, resolve to either instance. Unrelated implementations of one type, or two independent extensions of a common base, are ambiguity the framework can not resolve and throw IllegalStateException naming the type, the candidate classes and the remedy. The result is deterministic regardless of ServiceLoader iteration order.
DefaultColumnDefinition now caches GetValue and SetParameter instances from Database.getter() and setter().
is.codion.framework.server
EntityServerConfiguration.builder() no longer takes port parameters, consistent with ServerConfiguration.builder().
EntityServerAdmin get/set/is accessors (maintenanceInterval, idleConnectionTimeout, logLevel, traceToFile, tracingEnabled, and the per-pool collect/cleanup/timeout/size methods) de-beanified to the house name()/name(value) style. The underlying LoggerProxy and per-connection tracing methods retain their names.
AbstractRemoteEntityConnection, a failed remote iterator export no longer strands the open-iterator count, which pinned the pooled connection for the life of the session; the local iterator is closed and the count decremented before the exception propagates.
AbstractRemoteEntityConnection, the remote iterator's hasNext()/next()/close() now serialize on the connection proxy like every other remote call, no longer allowing two server threads onto the same JDBC connection concurrently.
EntityServer, connecting with a domain type the server does not host now reports the domain and the hosted domains, instead of surfacing as "LoginException: null".
EntityServer.disconnectClients() now uses the connections from its own snapshot rather than re-looking each one up through the throwing accessor, which aborted the sweep when a client disconnected concurrently.
EntityServer, a classpath domain model overriding a service loaded one is now logged.
AbstractRemoteEntityConnection, a remote iterator's close() now decrements the open iterator count before unexporting the iterator, which throws when it has already been unexported, previously stranding the count.
AbstractRemoteEntityConnection no longer extends UnicastRemoteObject, it exports each connection explicitly and only when RMI is enabled, so an HTTP-only server, ServerConfiguration.rmi(false), exports no per-connection remote object either, only the in-process reference the HTTP servlet already calls. EntityServer binds into the registry and exports connections only when RMI or the admin interface is enabled.
is.codion.framework.db.core
EntityConnection.cacheQueries(boolean) and the cacheQueries() getter replaced with a scoped, AutoCloseable EntityConnection.QueryCache returned by cacheQueries(). The cache can no longer be left enabled, try-with-resources closes it on the exception path, and scopes do not nest, a second cacheQueries() while one is active throws IllegalStateException.
A cached select result is now an unmodifiable list of immutable entities, so a shared cached instance can no longer be modified by one caller and observed modified by the next. Selects for update continue to bypass the cache and return mutable entities.
is.codion.framework.db.local
LocalEntityConnection.TRACES configuration key renamed from codion.db.traces to codion.db.tracing.retained, nested under codion.db.tracing to read as a pair and no longer a one-letter typo away from it.
DefaultLocalEntityConnection query caching moved behind the scoped QueryCache handle, the cache is cleared and disabled when the handle is closed.
is.codion.framework.db.rmi
RemoteEntityConnection.cacheQueries(boolean)/cacheQueries() removed from the wire protocol; query caching is now performed client-side in the connection proxy, so a cache hit no longer costs a network round-trip and serialization.
RemoteEntityConnectionProvider now reconnects to an unreachable-but-cached server by registry name, letting connect() decide; server discovery filters out servers with no connections available, which hid the very server still holding the client's session (existing sessions being exempt from the connection limit).
RemoteEntityResultIteratorWrapper now chains the RemoteException as the cause of the DatabaseException it throws, instead of discarding it.
RemoteEntityConnection client-side query cache now also serves selectSingle(Condition)/selectSingle(Select) and select(Key), sharing cache entries with the equivalent select(), consistent with the local and http tiers where these all route through select(Select).
EntityObjectMapper.returnType(FunctionType) added, registering the type a function's return value is serialized as and deserialized from over a json connection. A function called over one requires a registered return type, its FunctionType return type parameter being erased at runtime, and fails with a message naming the function and the registration.
EntityObjectMapper.ParameterType renamed JsonType, being what returnType() returns as well, and its get() now returns a JavaType rather than a Class. set(TypeReference) previously stored the reference's raw type, so a parameter registered as new TypeReference<List>() {} was deserialized as a raw List, leaving the caller holding a List.
EntityObjectMapper.returnType(ReportType) added, registering the type a report result is serialized as and deserialized from over a JSON connection, symmetric with returnType(FunctionType) and parameter(ReportType).
EntityObjectMapperFactory now logs a warning if no factory is registered for a given domain.
is.codion.framework.json.db
ErrorEnvelope and ErrorKind added, the wire form of a server side exception on the json error channel. The kind is a closed enum determining the http status, the server log severity and the exception the client reconstructs; nothing on the wire names a class.
ErrorKind.REPORT added, a report failure crossing the json error channel as its own kind rather than as a generic INTERNAL error, which would replace the message. The plugin strips the message of any engine type before it is thrown, so it is safe to send, and the client reconstructs it as a ReportException, which lives in common-db.
ErrorEnvelope, its mapper now (de)serializes through the public creator and getters alone, never the private fields, so it no longer fails on the module path where Jackson can not setAccessible() on a field of a package this module does not open to it. The whole error channel would break with an InaccessibleObjectException on the first error otherwise.
is.codion.framework.db.http
HTTP query caching moved client-side, a cache hit no longer costs a round-trip. The setQueryCacheEnabled/isQueryCacheEnabled requests are removed.
HttpEntityConnection message bundle key many_records_found renamed multiple_records_found, matching the LocalEntityConnection sibling and the MultipleEntitiesFoundException it populates. The English message is aligned with it as well.
A json connection no longer deserializes the error response, which was a readObject() on the most travelled failure path of the tier, one an attacker able to inject a single response could reach. The typed ErrorEnvelope is parsed and the exception reconstructed from its kind. The serial connection, being a java serialization channel by definition, is unchanged.
Neither a stack trace nor a cause chain crosses the wire in json mode; a server originated exception carries the stack trace of the client throw site. An unmatched server exception carries a generic message and a correlation id identifying the server log entry.
HttpEntityConnection.close(), startTransaction(), commitTransaction() and rollbackTransaction() no longer deserialize the response, which carries no payload.
A json connection now sends and receives a function's return value as json, rather than receiving a serialized object.
A json connection now sends and receives a report's result as json, rather than receiving a serialized object, symmetric with a function. A report filled over one requires a registered return type, EntityObjectMapper.returnType(reportType), resolved before the request, so a report exported to bytes reaches the client base64 encoded in json rather than as a serialized object. With an injected domain a json connection now performs no java deserialization; the entities route, the last replying with a serialized object, is the one a client avoids by injecting its domain.
A json connection decoding an error envelope no longer throws from the decode. A referential integrity Operation this client does not know, or a modified column naming an attribute absent from its domain, degrade to the generic exception rather than raising a client side exception in place of the server's.
A json connection reconstructs a report failure as a ReportException, via ErrorKind.REPORT, rather than the generic DatabaseException the unmatched path yielded, so the message a serial client receives now reaches a json client as well.
is.codion.framework.servlet
EntityService, the isQueryCacheEnabled and setQueryCacheEnabled routes (serial and json) removed, query caching is a client-side concern.
EntityService, enabling SECURE no longer leaves a cleartext connector listening on PORT alongside the secure one, which served the whole api, basic authentication credentials included, in the clear. The javalin ssl plugin adds an insecure connector by default; it is now disabled.
EntityService, a malformed clientId or Authorization header now returns 401, as a missing one already did, rather than 500. The status of an error response is now that of its ErrorKind, categorizing by whose fault the request was, and its severity decides the log level. An optimistic locking conflict is a 409 logged at DEBUG, an unmatched exception a 500 logged at ERROR.
EntityService responds to an error on a json route with an ErrorEnvelope rather than a serialized exception, and on a serial route with a serialized exception, as before. The message of an unmatched exception is replaced with a generic one, only its correlation id crossing the wire.
EntityService, the close and transaction routes are served by a single handler in both modes, they carry no payload in either direction. The entities route remains the one route replying with a serialized object in json mode, which a client avoids by injecting its domain.
EntityService.information() no longer reports the insecure port when only the secure port is listening.
EntityService.remoteHost() javadoc now documents that X-Forwarded-For is a client controlled header, honored for display and logging only, never for authorization.
EntityService.SECURE_PORT javadoc corrected, it described the insecure port.
EntityService, the json function route responds with application/json rather than an octet stream, writing the return value as the registered return type.
EntityService responds to a report on a json route with the report result as json, resolving its registered return type before filling, rather than a serialized object. The report route joins the function route in carrying no serialized object in json mode, leaving the entities route the only one that does.
EntityService now classifies a ReportException as ErrorKind.REPORT rather than INTERNAL, passing its message through verbatim, the plugin having already stripped any engine type from it. A report failure over a json route now carries the same message it carries over a serial one, rather than a generic internal-error message.
is.codion.framework.model
EntitySearchModel.Selection.single() added, an ObservableState indicating whether exactly one entity is selected.
AbstractEntityApplicationModel, the custom-Preferences constructor javadoc now notes that startup preferences (frame size, look and feel, default username) are read from the default root before the model exists.
EntityConditionModel.Modified no longer throws when snapshotting the condition state, which it does on every condition change event. An enabled condition with a missing operand (reachable with autoEnable off) is reported as modified rather than throwing out of the listener chain; the query time evaluation remains the failure.
EntityConditionModel, an equality search on a LocalTime column at the last second/minute/hour of the day no longer builds an interval wrapping around midnight, which matched nothing; plain equality is used instead.
EntityConditionModel.get(ForeignKey) now reports a condition model that is not a ForeignKeyConditionModel rather than throwing ClassCastException.
AbstractEntityTableModel.onInsert() no longer clears the selection, which defaulted the editor via the selection sync, overriding the UI's clear-after-insert configuration. The selection is now preserved by the items model, and since the selection no longer notifies when it has not changed, the editor is left holding the inserted entity.
AbstractEntityTableModel, the edit/query model entity type mismatch message now names the edit model's entity type rather than its Entities instance, and updated(ForeignKey, Map) now documents that the rows are neither re-sorted nor re-filtered.
EntitySearchModel, an update is now reconciled into the selection with a single set(), a remove followed by an add left the selection transiently missing the updated entities, which cascaded through the condition operands bound to it.
EntitySearchModel, the search string is now trimmed before spaces are replaced with wildcards, the trim previously had no effect with spaceAsWildcard enabled.
EntityQueryModel and EntitySearchModel, exception message typos corrected.
AbstractEntityEditor, the column combo box models no longer register strong listeners on the static PersistenceEvents registry, which pinned each one for the lifetime of the application, refreshing from the database on every persist event. Weak listeners are used, held by the ComboBoxModels instance, matching the editor's own foreign key listeners.
EntityEditor.EditorValue.propagate(Attribute, Function), the propagators are no longer applied to an unchanged value, two attributes propagating to each other, or an attribute propagating to itself, previously recursed until StackOverflowError.
EntityEditor.EditorValue.set(Entity, Object) now applies the propagated attributes' own propagators, consistent with set(Object); an attribute is propagated to once, so a cycle terminates.
AbstractEntityEditor, a foreign key value is now replaced in place when the referenced entity is updated or deleted elsewhere. It was cleared and set, which wrote a null through the notification graph, and threw IllegalStateException when the foreign key was not editable.
EditorLink.Builder.build() no longer claims the detail editor's present() predicate, DetailEditors.add(EditorLink) does. A link which was built but never added left the predicate permanently locked.
EntityEditor.Modified.attributes() javadoc now states that only attributes with an associated EditorValue are reported, and that the set may be empty while the modified state is true.
ForeignKeyModelLink.Builder.build() now returns the ForeignKeyModelLink rather than the plain ModelLink it wraps, the sealed type was previously unobtainable and EntityModel.DetailModels.get() reported every link as a ModelLink.
EntityModel.DetailModels.add(ModelLink) now validates the foreign key of a ForeignKeyModelLink, which build() unwrapping had rendered unreachable; a foreign key not based on the detail entity type or not referencing the master entity type is rejected on add() rather than at first selection. The uniqueness requirement remains on the implicit add(EntityModel) path, where it belongs, a detail model referencing its master via multiple foreign keys being exactly what add(EntityModel, ForeignKey) is for.
ModelLink.Builder.build() no longer configures the linked model, DetailModels.add(ModelLink) does. A link which was built but never added left conditionRequired() set and the foreign key condition persisted.
ForeignKeyModelLink, setConditionOnInsert now searches by all inserted entities of the referenced type rather than the first one.
EntityExport.Builder.export() now throws IllegalStateException when no attributes are included, rather than silently producing no output.
EntityExport no longer re-selects a referenced entity the exported entity already carries, an export of entities loaded with the default reference depth no longer issues a select per distinct foreign key value. The referenced entity is used only if it contains every attribute the export requires.
EntityExport.ExportAttributes.Builder.order(List), attributes left out of the order are now sorted by caption, as they are without an order, rather than falling back to definition order.
EntityExport.ExportAttributes.Builder.include(Collection) now copies the given collection, which was previously validated at include() and read at build().
EntityExport, an EntityNotFoundException thrown for a missing referenced entity now chains the original as its cause.
AbstractEntityTableModel.onSelectionChanged() javadoc now states that the editor keeps its entity across a refresh, the selection notifying only when it actually changes and a refreshed row being the same row. A refresh must not clobber an edit in progress; optimistic locking catches a write based on a stale instance.
is.codion.plugin.jasperreports
JRReportType and DefaultJRReportType removed along with JasperReports.reportType(String), a report type names a report and says nothing of the engine backing it; ReportType.reportType(String) serves. A domain API naming a report no longer depends on this plugin, and the serialization whitelist no longer opens is.codion.plugin.jasperreports.* for the report type travelling to the server.
AbstractJRReport.fill() and JasperReports.fillReport() now throw ReportException as documented. JasperFillManager throws JRRuntimeException for an incompatible parameter value, previously passed through unwrapped, and a client would have to carry the engine to deserialize the failure of a report it need never have heard of.
FileJRReport.load() no longer wraps its own ReportException in another one, burying the message a getCause() deep, as ClassPathJRReport.load() already avoided.
JRReport is now generic in the type it produces when filled, JRExport added along with JasperReports.export(JRReport, JRExport) and JasperReports.export(JasperPrint, JRExport). A report registered with an export fills to whatever the export produces, PDF for example, the export running where the report is filled, on the server for a remote connection, so only the exported document crosses the wire and no reporting engine is required of the client. JRExport provides PRINT, PDF and XML, any other JasperReports exporter being a lambda. PDF requires the net.sf.jasperreports:jasperreports-pdf artifact, which is not a dependency of this plugin and which nothing requires, so it is neither resolved on the module path nor included in a jlink image unless named via --add-modules.
AbstractJRReport.fill(), JasperReports.fillReport() and an export now drop the engine exception behind a failure, keeping its message and stack trace but not the exception itself as the cause. The exception a report failure throws now crosses to the client carrying no JasperReports type, which the client would otherwise need on its classpath to deserialize the failure of a report it need never have heard of. The server logs the exception in full before rethrowing.
JRExport.SERIALIZED and JasperReports.loadPrint(byte[]) added, the export serializing the filled report to bytes and loadPrint reconstructing the JasperPrint from them. A client with the reporting engine, one displaying reports with a JRViewer, keeps a JasperPrint report over a connection which can not transfer one, a JSON connection for one, filling it to bytes and reconstructing it. loadPrint keeps the cause of a failure, unlike the fill and export paths, reconstructing the report being the client's last step, its failure crossing no wire.
JasperReports, the dropped cause's message is now folded into the ReportException message, the outer exception often naming only the operation and the cause naming what went wrong. Combined with ErrorKind.REPORT, a report failure over a json connection now carries a message as informative as the one a serial connection carries.
ExportingJRReport.toString() now includes export type.
is.codion.swing.common.model
DefaultSwingFilterComboBoxModel.getElementAt() now reads by index rather than copying the whole included list per element, which a full-model scan such as key-selection type-ahead made quadratic once the combo box items began returning a snapshot.
is.codion.swing.common.ui
ToggleMenuItemBuilder.PERSIST_MENU configuration key no longer contains a duplicated class name segment.
Completion.COMPLETION_MODE configuration key suffix shortened from completionMode to mode, no longer restating the class name.
ModifiedIndicator.INDICATOR_CLASS and ValidIndicator.INDICATOR_CLASS configuration key suffixes changed from indicatorClass to implementation, no longer restating the class name.
ColumnConditionPanel.Builder.name() added, naming each input component by its role, operator/equal/lower/upper/in/enabled suffixed onto the given base name, typically the column identifier. A tool driving the UI, such as the Swing MCP server, now identifies the focused condition field and its column via Component.getName(), the way it already does an attribute's edit field. FilterTable and EntityTablePanel name their condition panels by the column identifier.
is.codion.swing.framework.ui
ReferentialIntegrityErrorHandling.REFERENTIAL_INTEGRITY_ERROR_HANDLING configuration key suffix shortened to handling, no longer restating the full class name.
FrameworkIcons.FRAMEWORK_ICONS configuration key suffix changed from frameworkIconsName to implementation, no longer restating the full class name.
EntityTablePanel, a summary-visible state of true on a panel that ends up without a summary panel no longer throws during initialize() and permanently bricks the panel; it is silently downgraded before the availability validator is armed.
EntityTablePanel.deleteSelected() progress dialog is no longer titled "!deleting!"; it now uses the correct edit-panel message bundle and logs the exception, unified with the DeleteCommand control path.
EntityTablePanel.Config.INCLUDE_FILTERS javadoc corrected to state the actual default of false.
EntityTablePanel.Config copy constructor no longer drops the editable-attributes validator and no longer shares the FilterTable.Builder with the original, closing a post-build mutation gap.
EntityTablePanel, various javadoc corrections (editAttributeSelection/SelectionMode, TOGGLE_SUMMARIES, EXPORT, RefreshButtonVisible, auto-resize-mode selection) and internal deduplication of the constructors and export()/exportPanel().
EntityTablePanel.ControlKeys.COPY_CELL and COPY_COLUMN no longer declare default keystrokes they never bound; the keystrokes are owned by the underlying FilterTable.ControlKeys, now noted in their javadoc, matching the keystroke-less COPY_ROWS sibling.
EntityEditPanel no longer leaks its active-panel state into a static group forever; membership now tracks displayability via addNotify()/removeNotify(), so discarded dialog edit panels are cleaned up and focus switching no longer walks dead states.
EntityEditPanel.Config.excludeFromSelection() now validates that the attributes belong to the underlying entity, as its javadoc has always advertised, instead of silently ignoring foreign attributes.
EntityEditPanel, the CLEAR control now routes exceptions to onException() like its insert/update/delete siblings, and configureControls() now rejects calls made after the panel is initialized.
EntityEditPanel.refresh()/update() javadocs now document the synchronous IllegalStateException thrown for a non-existing/unmodified active entity.
EditorComponents, the EditorComponent.set(JComponent) and set(ComponentValue) guards now also reject a pending component builder, closing a one-component-per-attribute invariant bypass.
EntityPanel, the edit-window close handler no longer yanks a just-embedded edit panel to HIDDEN; it now carries the same embed-transition guard as the detail-window sibling.
EntityPanel.editPanelState() now validates against the enabled edit states and rejects state changes on a panel without an edit panel, instead of silently desyncing or throwing an obscure NPE. defaultPanel() now honors a pre-initialize editPanelState() set rather than the configuration constant.
EntityPanel, EDIT_PANEL_CONSTRAINTS javadoc value type corrected to String, the editPanelConstraints field typo fixed, and the enabledEditStates() IllegalArgumentException message corrected to describe the actual rule.
TabbedDetailLayout, the enabledDetailStates() IllegalArgumentException message corrected, and the divider resize now clamps to the minimum divider location for left/right symmetry.
WindowDetailLayout, navigation into a windowed detail now actually shows the window; WindowDetailController implements display()/activate() instead of relying on empty interface defaults. A detail window is no longer created just to hide it, and the RejectEmbedded message names the correct class.
EntitySearchField edit control is now enabled only when a single entity is selected, no longer editing an arbitrary entity and silently collapsing a multi-selection.
EntitySearchField, a superseded search worker's onDone() no longer clears the state of a newer worker; the cleanup is now identity-guarded.
EntitySearchField, a builder-supplied separator containing regex metacharacters now splits correctly; the separator is quoted before use as a split pattern.
EntitySearchField.Builder.singleSelection() no longer clobbers an explicitly configured selectionToolTip; the tooltip default is resolved at build time. Duplicate selector-table key binding and a dead result-limit-message line removed.
EntityApplicationPanel.ApplicationLayout.display() is now abstract and the interface is no longer @FunctionalInterface; a lambda layout can no longer silently inherit a no-op display() that drops keyboard navigation and display().request().
EntityApplication, the login validator no longer leaks a connected provider when a connectionProvider(Function) is configured; the validator now validates through that function, and the reuse branch precedes the function branch.
EntityApplicationPanel, handleUnsavedModifications() no longer throws IllegalStateException mid-exit when a modified panel has no edit panel; the edit-panel access is now guarded.
EntityApplicationPanel, a maximized frame no longer stores the screen size as its restore size, so un-maximizing after a restart no longer leaves the window full-screen.
EntityApplicationPanel, open non-cached auxiliary panels now have their preferences stored during store() rather than only on window-close, which runs after the final preferences flush at exit.
EntityApplicationPanel.DefaultApplicationPanelFactory now looks up the panel constructor by the declared model class rather than the runtime model class, so a model factory returning a subclass no longer fails with NoSuchMethodException.
EntityApplicationPanel, the SQL trace viewer consumer now appends to its own viewer rather than the field, and exit()'s JVM-wide window disposal is now documented.
ApplicationPreferences, corrupt on-disk preferences (e.g. a malformed frame size) no longer crash application startup; parsing failures are logged and defaults used, matching EntityTablePanelPreferences.
EntityTableExport, the all-rows export now snapshots the table items before draining them on the background thread, instead of iterating a live view that a concurrent refresh or persist event could mutate mid-export.
EntityTableExport, dropping a dragged node onto its own position no longer throws IndexOutOfBoundsException; the insert index is recomputed after the moved nodes are removed.
EntityTableExport, moving is now gated on a shared parent rather than a shared tree depth, so a mixed-parent selection can no longer corrupt the tree or throw during a keyboard/drag move.
EntityTableExport, toggling show-hidden off no longer silently drops included hidden attributes from the export; included nodes are preserved across the filter.
EntityTableExport, the all-rows/selected-rows radio group now falls back to all-rows when the table selection is cleared, instead of leaving neither selected.
EntityTableExport, ConfigurationFile.filename() no longer garbles or throws on a configuration file not ending in .json, and the export/configuration save dialogs append the .tsv/.json extension when the user typed none.
EntityTableExport, a failed (not only cancelled) file export now removes the truncated output file, and the configuration-file list renderer reuses a single panel rather than allocating one per cell paint.
EntityDialogs, the add-entity dialog now clears the editor to defaults before the dialog is built rather than in its shown-callback, so a modified-warning veto simply prevents the dialog opening instead of throwing an uncaught CancelException over a visible dialog, matching the edit-entity sibling.
EntityTablePanel.containsConditionPanel() added; the selection dialog now uses it instead of probing condition() via try/catch IllegalStateException.
EntityComponents.toggleButton() now rejects nullable attributes with the same guard as checkBox(), a two-state toggle can not represent a three-state attribute.
EntityComponents, the "no dateTimePattern defined" exception now names the offending attribute.
EntityComboBox.addFocusListener() javadoc now documents that the editor-component routing is based on editability at call time.
EditAttributePanel no longer arms its updating state before creating the update task, which validates each entity in full, where the panel's ok control validates the edited attribute alone. An entity invalid on some other attribute passed the panel's gate and threw from the task, leaving the modal dialog with both controls disabled, and the application frozen. The result handler now closes the dialog even when an after-update consumer throws.
SelectQueryInspector now renders EntityQueryModel.select(), rather than a select rebuilt from the model's parts. It passed the default attributes to Select.Builder.include(), a replacing setter, which the following include() call then discarded, so a query model with default attributes was rendered as a select of every column.
EntityTablePanel no longer binds the INSPECT_QUERY control when no EntityQueries.Factory is available, which is the case on a remote client, the factory being provided by the db-local module. It previously threw IllegalStateException on each press.
EntityViewer fetches the entity to view on a worker rather than the event dispatch thread. A foreign key referencing a deleted row now renders as such rather than throwing out of the tree expansion listener.
KeyboardShortcutsPanel now documents the entity viewer, CTRL-ALT-V, which is enabled by default.
EntitySearchFieldPanel now propagates its name to the inner search field, which is what receives focus, so a tool driving the UI identifies it as it does a plain search field, matching EntityComboBoxPanel and the other composite fields.
EntityConditionInspector added, a UiInspector projecting the ConditionModel behind a focused condition field for the model_state MCP tool, its attribute, whether it is a query condition or a client-side filter, its operator, operands and enabled state. EntityTableModelInspector defers to it when focus is in a condition field, reporting the table rows and selection elsewhere.
is.codion.tools.generator.model
Generator model, configuration keys moved from codion.domain.generator.* to codion.tools.generator.*, no longer squatting in the core domain namespace.
is.codion.tools.generator.ui
Generator UI, configuration keys moved from codion.domain.generator.* to codion.tools.generator.*, no longer squatting in the core domain namespace.
is.codion.tools.monitor.model
EntityServerMonitor.SERVER_MONITOR_UPDATE_RATE configuration key moved from codion.server.monitor.updateRate to codion.tools.monitor.updateRate.
is.codion.tools.swing.mcp
SwingMcpServer.HTTP_PORT configuration key moved from codion.swing.mcp.http.port to codion.tools.mcp.port.
0.18.79
is.codion.common.reactive
Value.link(), a chain of value links no longer falsely reports a cyclical link; genuine transitive cycles are still detected.
Value.link(Observable) now rejects a duplicate link instead of silently leaking an unremovable feeder, consistent with link(Value).
Value.set() now rejects a locked change before running validators, so validator side effects no longer execute for a refused mutation.
Value, State and ValueLink javadocs corrected to state the actual contract, listener management is thread-safe while mutation and notification are single-thread by design.
Change.hashCode() now uses deep hashing, consistent with its deepEquals based equals, so array-valued changes that are equal also hash equally.
javadocs updated, some minor api improvements.
is.codion.common.utilities
javadocs updated, some minor api improvements.
is.codion.common.db
javadocs updated, some minor improvements.
AbstractConnectionPoolWrapper, the redundant wrapper-level checkout validation and the codion.db.pool.validateConnectionsOnCheckout property removed; both pool implementations validate natively.
DefaultConnectionPoolCounter, snapshot statistics now return copies of the pool states instead of aliasing the live ring buffer mutated by the collector thread.
DefaultConnectionPoolCounter.statistics(0) no longer includes the pre-allocated empty ring states.
DefaultConnectionPoolCounter, the check-out time average division is now guarded inside the lock, no longer racing a concurrent clear.
DefaultConnectionPoolCounter.resetStatistics() now also resets the per-second request window.
is.codion.common.model
javadocs updated, some minor improvements.
DefaultFilterModelItems.replace(), now fires a delete event when a replaced item moves from included to filtered.
DefaultFilterModelItems, item listener insert/remove/sort ranges corrected to be inclusive.
DefaultRefresher, a synchronous refresh no longer clobbers an in-flight asynchronous refresh worker.
DefaultRefresher, exceptions from result consumers now propagate on the synchronous path instead of being reported as refresh failures.
DefaultFilterComboBoxModel.replace(Map), now updates the selected item when it is among those replaced.
DefaultFilterComboBoxModel.set(), now clears the selection when filterSelected is enabled and the selected item is excluded.
DefaultFilterComboBoxModel.set(), now rejects null items, null being the reserved null item sentinel.
DefaultFilterComboBoxModel, ItemComboBoxModel.selected() no longer rejects the null item.
DefaultFilterComboBoxModel.add(), an item no longer ends up in both the included and filtered partitions.
DefaultFilterComboBoxModel, the selection is now cleared when the selected item is the last one removed.
DefaultFilterComboBoxModel.Builder.includeNull(false) now clears any previously set null item.
DefaultFilterComboBoxModel, item change events no longer publish a live view of the underlying items.
DefaultFilterComboBoxModel.selector() now searches all items, not just the included ones.
FilterComboBoxModel.ItemFinder.value() return value is now @nullable, item values may legitimately be null.
is.codion.common.rmi
javadocs updated, some minor improvements.
is.codion.framework.domain
javadocs updated, some improvements and fixes.
ImmutableEntity now precomputes cached derived values during construction, keeping shared immutable instances genuinely read only and thread safe.
ImmutableEntity and EmptyEntity no longer re-serialize the payload already written by the DefaultEntity layer, halving the serialized size of foreign key reference graphs.
ImmutableEntity now deduplicates referenced entities by source instance identity, fixing unbounded recursion on cyclic unsaved graphs and the collapse of distinct instances sharing a key.
Entity.equalValues() no longer changes its answer for a derived attribute depending on whether it has been read.
DefaultEntity, changing or removing a foreign key reference column now invalidates the cached referenced key even when the foreign key entity value is not loaded.
DefaultEntity.remove() now clears the derived, toString and foreign key key caches, consistent with set().
SingleColumnKey and a single-column CompositeColumnKey now produce equal hash codes, honouring the equals/hashCode contract across the two implementations.
SingleColumnKey.hashCode is now recomputed on deserialization rather than read from the stream.
Condition combinations consisting solely of empty conditions now stringify to an empty string instead of an invalid "()".
Case-insensitive String conditions now apply UPPER() to the order operators (<, <=, >, >=) as well, not just equality.
Chunked IN clauses now join with uppercase AND/OR keywords.
is.codion.framework.domain.db
javadocs updated.
is.codion.framework.db.core
javadocs updated, some improvements and fixes.
EntityConnection.Select.timeout() now returns OptionalInt, an absent timeout falls back to the connection query timeout, so entity selects now honor queryTimeout and codion.db.queryTimeout.
is.codion.framework.db.local
javadocs updated, some improvements and fixes.
DefaultLocalEntityConnection.insertSelect()/updateSelect(), all loaded lazy columns are now re-selected, not just the first one per entity.
DefaultLocalEntityConnection.execute(FunctionType) now commits on success and rolls back on failure, consistent with execute(ProcedureType) and report(); an operation abandoning a transaction is rolled back and reported.
DefaultLocalEntityConnection.select(Collection) and dependencies() now chunk by the maximum parameter count, consistent with delete(Collection).
DefaultLocalEntityConnection.delete(Collection) now deduplicates keys, duplicates no longer trigger a spurious DeleteEntityException.
DefaultLocalEntityConnection.iterator(), foreign key population now runs under the connection monitor.
DefaultLocalEntityConnection.connection() now reads the connection under the connection monitor.
Entity result iterators now map SQLExceptions through the database dialect.
Case-insensitive order by clauses now retain their direction and null ordering, no longer silently dropping DESC and NULLS.
Update.all() now produces valid SQL, no longer appending a dangling WHERE clause.
The select column order is now stable across JVM runs.
is.codion.framework.db.rmi
is.codion.framework.db.http
javadocs updated, some improvements and fixes.
is.codion.framework.json.domain
is.codion.framework.server
javadocs updated, some improvements and fixes.
is.codion.framework.model
AbstractEntityEditor.execute() and supersede() protected again.
DefaultEntityModel, DefaultEntityEditModel and DefaultEntityApplicationModel renamed AbstractEntityModel, AbstractEntityEditModel and AbstractEntityApplicationModel, now abstract, consistent with the other Abstract* extension bases.
EntityComboBoxModel.Builder now yields independent models on repeated build() calls, no longer sharing query state.
EntityComboBoxModel.ForeignKeyFilter.link(), pre-set filter keys are no longer wiped when linking a master that has not been refreshed.
EntityComboBoxModel.Builder.attributes() now defensively copies the given collection.
javadocs updated, some improvements and fixes.
is.codion.framework.model.test
javadocs updated.
is.codion.framework.server
EntityServer, jmx runtime metrics added along with prometheus and grafana config examples.
Pooled remote iterators no longer stream on a connection returned to the pool; the underlying connection is now pinned to the client until the iterator is closed or times out.
LocalConnectionHandler.invoke() now throws IllegalStateException for calls received after the connection has been closed, instead of executing against a discarded connection.
LocalConnectionHandler.methodTraces() now synchronizes consistently with the other tracer accessors, no longer synchronizing on the swappable tracer field.
DefaultRemoteEntityResultIterator.lastAccessTime is now volatile, safely published to the connection maintenance thread.
is.codion.swing.common.model
DefaultListSelection.items().remove(), removing an item not in the selection is now a no-op instead of throwing.
DefaultListSelection, setLeadSelectionIndex() now fires the changing() event, extending selection change coverage to shift based extension.
DefaultListSelection, structural re-indexing no longer fires the changing() event.
DefaultListSelection, the adjusting protocol is now reentrant, no longer breaking a caller's grouping.
DefaultListSelection, selection facades now notify only when their value actually changes.
DefaultListSelection.items().set(Collection), now enforces locking and validators, consistent with the set(List) overload.
DefaultSwingFilterComboBoxModel, a selection change now fires a (-1, -1) list data event instead of invalidating the whole list.
DefaultSwingFilterComboBoxModel, the redundant refresher override removed, the common model's Dispatcher based refresher is used directly.
is.codion.swing.common.ui
javadocs updated, some improvements and fixes.
is.codion.swing.framework.model
javadocs updated, some improvements and fixes.
is.codion.swing.framework.ui
javadocs updated, some improvements and fixes.
is.codion.plugin.hikari.pool
HikariConnectionPoolWrapper.close() now marks the pool closed and stops the statistics collector even if shutdown() is interrupted.
is.codion.plugin.tomcat.pool
TomcatConnectionPoolFactory, the idle timeout now maps to minEvictableIdleTimeMillis (idle eviction) instead of suspectTimeout (a connection leak warning threshold).