As you said, the callback method is called the second time if the object is detached or retrieved from the database.
I cannot explain this exactly, but I can think of the scenario described below when dirty fields were not detected before the second save() call and, therefore, @PreUpdate callback was not called. Or it could just be a bug in your version of EclipseLink.
UPDATE
In the JPA 2.0 specification, I found the following, which is exactly your behavior (3.5.2. Semantics of lifecycle callback methods for objects):
Note that this is implementation-dependent, depending on whether PreUpdate and Subsequent PostUpdate callbacks occur when an object is saved and subsequently modified in a single transaction, or when the object is modified and subsequently deleted in a single transaction. Portable applications should not rely on this behavior.
source share