oscerd opened a new pull request, #29077:
URL: https://github.com/apache/camel/pull/29077

   Fixes [CAMEL-26235](https://issues.apache.org/jira/browse/CAMEL-26235), 
found while adding the catalog body types (CAMEL-24961).
   
   ## 1. No operation: NullPointerException instead of a clear error
   
   **Was:** Without the `CamelHazelcastOperationType` header and without the 
`defaultOperation` option, the producers of `hazelcast-map`, 
`hazelcast-multimap`, `hazelcast-replicatedmap`, `hazelcast-list`, 
`hazelcast-set`, `hazelcast-ringbuffer` and `hazelcast-pncounter` switched on a 
null operation and failed with a `NullPointerException` ("operation" is null).
   
   **Now:** `HazelcastDefaultProducer.lookupOperation`, which every one of them 
uses, fails with an `IllegalArgumentException`: "No operation to perform: set 
the CamelHazelcastOperationType header or the defaultOperation option of the 
endpoint". `hazelcast-queue` and `hazelcast-topic` default to `add` and 
`publish` and are not affected.
   
   ## 2. map consumer: TTL expiry gives no event
   
   **Was:** `MapEntryListener` extended the added, updated, removed, evicted, 
merged and cleared listeners of Hazelcast but not `EntryExpiredListener`, and 
Hazelcast sends an expiry only to that listener, so an entry whose time to live 
ended never reached the route.
   
   **Now:** `MapEntryListener` also extends `EntryExpiredListener`, and 
`CamelMapListener.entryExpired` sends an `expired` event as the multimap and 
replicated map listener does: the `CamelHazelcastListenerAction` header is 
`expired`, the key is in `CamelHazelcastObjectId`, and there is no body, as for 
`evicted`.
   
   ## 3. list: get without CamelHazelcastObjectIndex fails with a 
NullPointerException
   
   **Was:** `get` unboxed the null index of a message without the 
`CamelHazelcastObjectIndex` header.
   
   **Now:** It fails with an `IllegalArgumentException`: "The get operation 
needs the index of the item in the CamelHazelcastObjectIndex header".
   
   ## 4. list and set: getAll puts the live proxy in the body
   
   **Was:** `getAll` set the distributed `IList` or `ISet` proxy itself as the 
body, so later steps read the live collection and changed the distributed one 
when they changed the body.
   
   **Now:** `getAll` sets a copy: an `ArrayList` for the list and a 
`LinkedHashSet` for the set, which keeps the order in which the set returned 
its items.
   
   ## 5. queue: removeIf always fails, drainTo without its header passes null
   
   **Was:** `removeIf` called `IQueue.removeIf`, which removes through the 
iterator, and the iterator of a Hazelcast queue does not support remove: the 
operation always failed with an `UnsupportedOperationException` ("remove() is 
not supported!"). `drainTo` cast the `CamelHazelcastDrainToCollection` header 
and passed it as is, so without it the queue failed with a 
`NullPointerException`, and with a value that is not a `Collection` the cast 
failed.
   
   **Now:** `removeIf` tests the items the queue holds with the 
`java.util.function.Predicate` of the body and removes the matching ones with 
one `removeAll` call; the body is `true` when it removed an item. Without a 
`Predicate` body it fails with an `IllegalArgumentException`. `drainTo` without 
a `Collection` in the header fails with an `IllegalArgumentException` that 
names the header, before the queue is touched.
   
   ## 6. pncounter: getAndAdd with no body fails with a NullPointerException
   
   **Was:** `getAndAdd` unboxed `getBody(Long.class)` into a `long`.
   
   **Now:** Without a body that converts to a number it fails with an 
`IllegalArgumentException`: "The getAndAdd operation needs a numeric body: the 
number to add to the counter".
   
   ## 7. seda: a body that is neither Serializable nor convertible to bytes 
gives an unclear error
   
   **Was:** A body that is not `Serializable` was converted to bytes, and when 
that gave null the queue failed with "Null item is not allowed!". No body ended 
the same way.
   
   **Now:** The producer fails with an `IllegalArgumentException` before it 
adds anything: "The body must be Serializable or convertible to bytes to be put 
on the Hazelcast queue, but it is a <class name>" (the class, never the value), 
or "The message has no body to put on the Hazelcast queue".
   
   ## 8. Docs: replicatedmap intro and old header name in the samples
   
   **Was:** The replicated map page started with the intro of the instance 
component, and the XML and YAML samples of the replicated map, multimap, PN 
counter and ringbuffer pages set the old `hazelcast.operation.type` header.
   
   **Now:** The replicated map page has its own intro, and the samples set 
`CamelHazelcastOperationType` (the YAML samples in the `expression: constant: 
expression:` form). `CamelHazelcastOperationType` is now also declared for 
`hazelcast-pncounter`, whose producer reads it, so its page lists the header 
the samples set.
   
   ## Tests
   
   - `HazelcastProducerChecksTest` (new) runs against an embedded Hazelcast 
member: no operation on each of the seven producers (item 1), list `get` 
without the index (3), list and set `getAll` give a copy that does not follow 
the distributed collection and does not change it (4), `removeIf` on a real 
queue removes the matching items, duplicates included, and gives `false` when 
nothing matches, `removeIf` without a `Predicate`, `drainTo` without the header 
leaves the item in the queue (5), `getAndAdd` without a body leaves the counter 
at 0 (6), and a `hazelcast-seda` body that is not `Serializable` or no body 
adds nothing to the queue (7).
   - `HazelcastMapConsumerExpiredTest` (new) puts an entry with a time to live 
of one second on an embedded member and expects the `added` and then the 
`expired` event (2).
   - `HazelcastQueueProducerTest.removeIf` (mock) now expects the iteration and 
the `removeAll` of the matching items instead of `IQueue.removeIf`.
   
   Revert check: with the src/main changes reverted, 18 of the 18 new or 
changed tests fail, each for the old behaviour: the seven no operation cases, 
the list `get`, the PN counter `getAndAdd`, the two seda cases, and `drainTo` 
and `removeIf` without their input (13 tests) fail with the old 
`NullPointerException` instead of the `IllegalArgumentException`, `removeIf` on 
a real queue fails with "remove() is not supported!", the `getAll` body is the 
distributed list or set, the expiring entry gives no event at all, and the mock 
queue is never iterated. The 15 that pass are the unchanged tests of 
`HazelcastQueueProducerTest`.
   
   camel-hazelcast: 273 tests, 0 failures, 0 errors.
   
   ## Docs and generated files
   
   - `@BodyTypes`: the map consumer gives no body for `expired`; list and set 
`getAll` give a copy; the queue producer takes a `Predicate` for `removeIf`, 
gives a `Boolean` for it, and `drainTo` needs its header.
   - Map page: the consumer lists the five events and the right header name, 
and the samples compare with `evicted` (they said `envicted`, which never 
matched). List, set, queue and PN counter pages: `get` needs the index, 
`getAll` gives a copy, how `removeIf` and `drainTo` work, and `getAndAdd` needs 
a numeric body.
   - Regenerated `hazelcast-map.json`, `hazelcast-list.json`, 
`hazelcast-set.json`, `hazelcast-queue.json` and `hazelcast-pncounter.json`, 
and the catalog copies of these and of the eight changed pages. The new header 
of `hazelcast-pncounter` adds a header name builder to the endpoint DSL.
   - Upgrade guide entry for 4.24: `getAll` gives a copy, the map consumer 
routes `expired`, `removeIf` works, and the missing inputs fail with an 
`IllegalArgumentException`.
   
   ## Not changed
   
   - `removeIf` is not atomic: the queue offers no conditional remove, so the 
producer reads the items and then removes the matching ones; an item polled in 
between is simply not removed. Deprecating the operation was the alternative, 
but it works this way and the page says it is not atomic.
   - The `set` operation of the list keeps its message ("Empty position for set 
operation.") and the generic `IllegalArgumentException` of an unknown operation 
is unchanged.
   - The consumer section of the replicated map page still shows a multimap 
sample and says the update listener is missing, which it is not. Item 8 covers 
the intro and the samples' header name, so this is left for a follow-up.
   - With `transferExchange=true` the `hazelcast-seda` producer still drops a 
body that cannot be serialized (with a WARN), as `DefaultExchangeHolder` does; 
only the body-only path fails now.
   
   Main only, as the other fixes of the CAMEL-24961 follow-ups.
   
   _Claude Code on behalf of Andrea Cosentino (oscerd)_
   
   🤖 Generated with [Claude Code](https://claude.com/claude-code)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to