initial proposal for a stateless EntityAgent
This is just a rough draft to incite snarky comments, personal insults, and other feedback. :-)
The pull request introduces:
EntityAgent, a stateless entity manager, as proposed in #374,EntityHandleras place for operations common toEntityAgentandEntityManager, and- new callbacks, as described here.
I have not even started working on the specification side of this.
How about naming it EntityRepository, EntityAccessor, EntityService or EntityStore?
Or EntityController, EntityRegistry, EntityHub?
The name is just a suggestion, but I chose it based on the following reasoning:
StatelessEntityManageris (a) verbose, (b) ambiguous (is it a manager for stateless entities?), and (c) potentially a little misleading because it's not necessarily a truly stateless object.- I was looking for something that is similar to "manager", but which implied a more hands-off relationship with the entities. "Agent" is a good word for this.
- I didn't like options which implied coordination/orchestration, since that's not its role (it's the application program which does orchestration).
- Other options were things like "dispatcher" or "executor", and they almost work as a description of its role in insert/update/delete. But they're not a great description of an object which runs queries and returns data.
EntitySupervisordoesn't work because "supervisor" is a synonym for "manager", and this thing doesn't actually "manage" the entities. None of its entities are in the managed state.
EntityRepository
This would collide with terminology already adopted in Jakarta Data.
EntityService
It's not a service, because it's not a singleton. Well, at least, that's not how StatelessSession works in Hibernate, but admittedly this is something which still needs to be thought through and nailed down. In principle it maybe could be a singleton per persistence unit, but that would mean it couldn't have any operations for setting properties, cache mode, etc. Anyway, in the attached proposal it's not a service.
EntityStore
That sounds like a better name for the EntityManagerFactory, but doesn't sound like a good name for this thing.
EntityController
This is more along the lines of what I'm looking for, but I think EntityAgent is better. In particular, I'm trying to emphasize that it actually exercises less "control" than the EntityManager.
EntityRegistry
I don't like this suggestion at all. The whole point of a stateless session is that it doesn't maintain any sort of registry of entities. So this has almost the precise opposite of the word sense I'm looking for.
EntityHub
Not sure why it's a hub. What are the spokes here? The entities? Again, the point of this object is that it doesn't maintain its relationship with the entities in a stateful way.
Q: Should <T> T getReference(Class<T>, Object id) be here? Maybe I missed it? The thought is that to perform insert() we need to build an entity bean and want to use getReference() for the ManyToOne properties when we do that.
Syntactic thought: get() could be namedfindOne() and getMultiple() could be named findList()
Syntactic thought: The Java Collections API uses addAll(), removeAll(). The thought is that the "Multiple" part could be "All" to be closer to the collections API. For myself, I don't see a lot of API use "Multiple" per se so that sticks out a little bit to me.
Currently, the get() doesn't say that it throws EntityNotFoundException [yet]. The 3 options I believe are: (1) throw EntityNotFoundException, (2) Return Optional<T> or (3) Mark the response as JSpecify @Nullable. I'm thinking this is going to tend towards option 1 for more consistency with EntityManager?
Should
<T> T getReference(Class<T>, Object id)be here?
I was about to answer "no", but then I realized it does make sense in combination with fetch() and for setting up associations. And so, yeah, I guess or right, it should be there. Nice catch.
get()could be namedfindOne()andgetMultiple()could be namedfindList()
I want to be very explicit about the huge semantic difference between EntityManager.find() and EntityAgent.get() by giving them different names.
As to getAll() vs getList() vs getMultiple(), the thinking here is that getAll() sounds like it gets all entities of a given type. With respect to List vs Multiple I don't have a strong opinion. @sebersole and I weakly prefer Multiple but I doubt either of us are very motivated to argue about it.
getAll()
Yes, I would not propose that. It was more findList() vs getMultiple() ... but if the find part isn't really an option then "All" probably doesn't work because getAll would not be great.
very explicit about the huge semantic difference between EntityManager.find() and EntityAgent.get() by giving them different names.
Makes sense. The other option is along the lines of using something more like StatelessSession vs EntityAgent but I get it, naming is hard here when we have both concepts in close proximity. Hmmm.
Should insert(Object entity) be void to align with insertMultiple(List<Object> entities)? since the id is filled if the operation is successful.
@quaff I don't care much. I agree that returning the id is not necessary, but sometimes it might be convenient.
I've now made a good start on the spec side of this. I think I've got the impact on chapter 3 pretty much nailed.
This change will also have an impact on chapter 7, but I have not thought about that at all yet. An open question is: are we going to introduce a new @PersistenceAgent annotation or whatever, since @PersistenceContext EntityAgent agent doesn't really work. Or maybe we're just going to assume that people with use @Inject for this, and add it to the new section of the platform spec?
I guess we need analogs of runInTransaction() and callInTransaction(). I'm deeply offended by the naming asymmetry of runWithAgent() and callWithAgent(), but it's the best I can think of right now :-(
I'm deeply offended by the naming asymmetry of runWithAgent() and callWithAgent(), but it's the best I can think of right now :-(
Actually, no, it's not. Let's just add overloads which take the class of the kind of EntityHandler you want.
So:
List<Book> books =
factory.callInTransaction(EntityAgent.class, agent -> {
return agent.createQuery("from Book).getResultList();
});
This can even be some implementation-specific class. For Hibernate:
List<Book> books =
factory.callInTransaction(StatelessSession.class, session -> {
session.enableFilter("region").setParameter("region", region);
return session.createQuery("from Book).getResultList();
});
That's actually ... really nice.
This can even be some implementation-specific class
I'd say that as long as the type has a bound, that is indeed very nice. E.g.
<T extends EntityHandler> void runInTransaction(Class<T> handlerType, Consumer<T> action);
<R, T extends EntityHandler> R callInTransaction(Class<T> handlerType, Function<T,R> action);
I'd say that as long as the type has a bound, that is indeed very nice
Yup, that's exactly what I pushed.
EntityStore
That sounds like a better name for the
EntityManagerFactory, but doesn't sound like a good name for this thing.
FTR it does sound like a good name to me.
We've had other conversations about naming elsewhere... My personal conclusion was that:
EntityHandlercould be renamed toEntitySource, which will remind people ofDataSource, and indeed it's closer toDataSourcethan other interfaces are. We could also say it's more fitting because this interface is mostly about read operations, but that's a weaker argument IMO since, likeDataSource, it allows mutation through e.g. SQL queries or stored procedures. Instead, I'd say it's more fitting because it's mostly about a connection + HQL statements, likeDataSourceis mostly about connections (a single connection, when a transaction is active) and SQL statements.EntityAgentcould be renamed toEntityStore(which was suggested above, by @beikov), which conveys the meaning that "this is a direct interface, you put and get stuff". At least it does so better thanEntityAgent, which will confuse people, especially in this AI age :roll_eyes:
Hey @gavinking @lukasj . Did you have time to reflect on the name of EntityAgent/EntityStore?
We're trying to figure out proper naming for Panache 2, which has a bigger focus on stateless sessions, so I'd love to pick something that doesn't stray too far from whatever Jakarta Persistence will use...
EntityHandleras place for operations common toEntityAgentandEntityManager, and
The answer is in the description. This thing should be called EntityOperations 😅 That's how I call these types of interfaces in Panache.
As for EntityAgent I do find that name very confusing. I agree with EntityManager because it manages managed entities. That's definitely its job.
I could get behind EntityStore as the counterpart to EntityManager.
The Agent part for me associates more with augmentation rather than a thing that allows performing some simple CRUD. E.g. app monitoring agents or Java agents come to mind here...
This thing should be called EntityOperations 😅 That's how I call these types of interfaces in Panache.
EntityOperations was also one of the first ideas I had for the name.
But, I don't think we usually use plural in the interfaces for the spec APIs... How about:
EntityOperator(orEntityOperationProvider) to emphasise it's just about operations and not managing the state?EntitySource, I'm a bit torn about this one, since I somewhat like it if looked at in isolation, but then, assuming one uses a datasource to create an entity source, this starts to lean more towards some mappers/transformers...
EntityOperator for the top type seems OK to me.
I am warming to EntityBroker as an alternative name.
I am warming to
EntityBrokeras an alternative name.
This isn't awful, but it does sound odd to me. Any specific problem with EntityStore, which at least hints at a similarity with a "datastore", and thus at something closer to the data than the EntityManager?
@yrodiere neither the EntityManager nor its evil stateless twin represents the datastore, it represents an ephemeral interaction or conversation with the datastore. The closest concept to an "entity store" in our architecture is the EMF.
Also, there's a bit of an asymmetry between "Store" and "Manager". One is a thing which gets acted on while the other is the thing which acts on it. I want a word which emphasizes as much as possible the common role of these two constructs.
"Broker" sounded weird in my ears at first too. But I'm sorta getting used to it. I still prefer "Agent", but I can just imagine annoying people on Reddit dissing this term because it has nothing to do with autonomous agents in AI. (Of course, we really shouldn't make naming decisions based on speculation about what annoying people on Reddit might say.)
Thanks for the explanation!
@yrodiere neither the
EntityManagernor its evil stateless twin represents the datastore, it represents an ephemeral interaction or conversation with the datastore. The closest concept to an "entity store" in our architecture is the EMF.
That ephemeral nature is probably not immediately obvious to, say, CDI users, where scope is handled under the hood using proxies. Still, you're obviously right.
I just think that in the specific case of stateless session, the "ephemeral" nature is not really something that derives from our intent, but from practical considerations. Essentially we don't want to make it thread safe, want to keep performance acceptable, want to cache the connection (though in-transaction we could get it for each statement, it'd always be the same one), ... Being stateless, the stateless session could be a singleton.
Also, there's a bit of an asymmetry between "Store" and "Manager". One is a thing which gets acted on while the other is the thing which acts on it.
You could argue that it reflects the fundamental difference between the entity manager (which keeps state, an action queue, ... and organizes operations for you, triggering them when it feels it's necessary) and the stateless session (which obeys direct orders).
I want a word which emphasizes as much as possible the common role of these two constructs.
In my mind "entity" was that word :grin:
Of course, we really shouldn't make naming decisions based on speculation about what annoying people on Reddit might say
True, though naming being primarily about conveying meaning, our primary concern here is how people will understand the name -- ideally, when first hearing it. So Reddit kind of matters -- it's just not necessarily representative of our whole audience.
"Broker" sounded weird in my ears at first too. But I'm sorta getting used to it
I suppose we all will, like we did with EntityManager :)
I can definitely live with EntityBreaker (oh wait…😅), but you can't tell me with a straight face that newcomers will find it obvious what the semantics difference is between an EntityManager and an EntityBroker.
Existing users will learn and remember that EntityBroker is the non-managed counterpart to EntityManager, so I guess they'll be fine, and that's the crowd we're most interested in.
I've mostly recently heard the broker term be used for banking or exchanges, though I do remember something ancient using that term in Java. Was it CORBA or EJB or RMI? 🤔