How to perform centralized changes on objects in an EJB environment - java

I'm working on a project where I have to process incoming message files of different kind (xml, edifact, etc.). The project is built in jboss using EJBs for recurring tasks.
I'm not native do EJBs and the ways you use them, so I try to listen, what my colleagues say and what I read about it. One central concept, I've been told, is to keep logic out of you entities (them being only data storage objects), because the entities jar-file is included in every program using any of the services, and you do not want all those calling projects to be updated for any change in the logic, you want that on a central space.
Sounds kinda sensible to me. That is the place where I think EJBs come in to provide services that operate on the data. The problem I run into, is that my remote EJBs cannot alter any objects, because they are (of course) passed by value. Returning an altered version of the object isn't working either, because that object is already existing and referenced in different places.
How can I perform operations on objects, that modify the object in a centralized manner? I will need the same action on that object in dozens of projects. The only ways I can think of is adding a tool.jar, which defeats the purpose of EJBs and is not so different from putting the logic in the entities, or to add a camel route with jump back address which seems awfully complicated and hard to understand for code readers.
Either I misunderstand some basic principle, miss an important tool, or our design must have a serious flaw.
(To be a little more concrete: I have a Message-Entity, that has many attributes like recipient, sender, message size, ... set already. No for some kind of message, I have to do the same actions, which involve setting numerous fields in the message, and adding multiple entities, that need to be attached to the message-entity. My EJB could do all that, but the changes are lost of course, and returning the modified object does not work because of multiple references to the original message-entity).

I may be missing the point, but the entity objects are representations of database rows - why do you not just persist the changes from your remote session beans? The database is there precisely to provide a consistent view of state, so it's the ideal place for this.

Related

Where to syncronize inside a Java WebApp

My employer has currently given me a project that has me scratching my head about synchronization.
I'm going to first talk about the situation I'm in:
I've been asked to create a pdf-report/quotation-tool that takes data (from csv-files; because the actual database the data is on is being used by old IBM software and they for reasons (unknown) don't want any direct access to this database (so instead of making copies of the data to other databases, they apparently found it incredibly fine to just create a folder on the server with loads and loads and loads of CSV-files.)), this piece of software is to load data into the application, query it, transform where needed, do calculations and then return with a pdf-file to the end-user.
The problem here is that getting, querying, and calculating things takes a fair amount of time, the other problem is: they want it to be a WebApp because the business team does not want to install any new software, they're mostly moving towards doing everything online (since the start of the pandemic), it being a WebApp means that every computation has to be done by the WebApp and getting the data likewise.
My question: Is each call to a servlet by a separate user treated as a separate servlet and should I only synchronize the methods on the business logic (getting and using the data); or should I write some code that puts itself in the middle of the servlet, receives a user-id (as reference), that then runs the business-logic in a synchronized-fashion, then receiving data and returning the pdf-file?
(I hope you get the gist of it...)
Everything will run on Apache Tomcat 8 if that helps. Build is Java 11lts.
Sorry, no code yet. But I've made some drawings.
With java web applications, the usual pattern is for the components to not have conversational state (meaning information specific to a specific user's request). If you need to keep state for a user on the server, you can use the http session. With a SPA or Ajax application it's often easier to keep a lot of that kind of state in the browser. The less state you keep on the server the easier things are as your application scales, you don't have to pin sessions to servers (messing up load balancing) or copy lots of session state across a cluster.
For simple (non-reactive) web apps that do blocking i/o, each request-response cycle gets its own dedicated thread from tomcat's pool. That thread delivers the http request to the servlet, handles the business logic and blocks while talking to the database, then carries the http response.
(Reactive webapps are going to be more complex to build, you will need a non-blocking database driver and you will have less choices for databases, so I would steer clear of those, at least for your first web application.)
The threadpool used by tomcat has to protect itself from concurrent access but that doesn't impact your code. Likewise there are 3rd party middletier caching libraries that have to deal with concurrency but you can avoid dealing with it directly. All of your logic is confined to one thread so it doesn't interfere with processing done by other threads unless there are shared mutable data structures. Those data structures would be the part of the application where synchronization might be one of several possible solutions.
Synchronization or other locking schemes are local to one instance of the application. If you want to stand up multiple instances of this application then you need to be aware each one would be locking separately from the others. So for some things it's better to do locking in the database, since that is shared across webapp instances.
If you can make use of a database to store your data, so that you can rely on the database for caching and indexing, then it seems likely your application should be able to avoid having doing a lot of locking.
If you want examples there are a lot of small examples for building web apps using spring at https://spring.io/guides. These are spring boot applications that are self hosted so you can put them together quickly and run them right away.
Going rogue with a database may not be the best course since databases need looking after by DBAs. My advice is put together two project plans, one for using a database, and one for using the flat files. The flat file one will have to allow for addressing issues like handling caching, indexing data, replication of data from the legacy database, and not having standard tools that generate pdfs from sql queries. The alternative plan using a database should have a lot less sorting out of infrastructure and a shorter time til you can get down to cranking out reports.

Sharing web application for different clients

Our framework is Grails. Say domain.com contains an application and currently used by some client. If we want to allow another client with the same functionality but providing a separation for the data of two clients, so that they can't mix both, how to do this? And whenever we want to add n clients to this application, what is the best method to be followed, so that with less / no configuration we can share the common war file for these clients by separating the db.
How the real time web development handle these type of situations?
And, one more point is how to provide client1.domain.com works for client1 and client2.domain.com works for client2. How to make the war file (in Java / Grails) to work like this? Otherwise we have to programmatically control the clients with in the project for every feature to be allowed or unnecessarily maintain separate war file for each client, which will be a waste of resources.
You're describing multitenancy - create one table for N 'tenants' instead of N identical (or nearly) tables, but partition it with a tenant_id column, and use that to filter results in SQL WHERE clauses.
For example the generated code for findByUsername would be something like select * from person where username='foo' and tenant_id=3' - the same code as a regular call but with the tenant_id column to restrict within that tenant's data.
Note that previously simple things like unique constraints are now harder because you would want to restrict uniqueness within a tenant, but allow a value to be reused across tenants. In this case changing the unique constraint to be on the combo of username and tenant_id works and does the heavy lifting in the database.
For a while there were several related plugins, but they relied on tweaking internal APIs and some features broke in newer Hibernate versions. But I believe that http://grails.org/plugin/multi-tenant-single-db is active; it was updated over a year ago, but it is being used. Contact the authors if it looks like it'll be what you need to be sure it's active. Note that this can only work with Hibernate 3.x.
Hibernate 4 added support for multitenancy, but I haven't heard much about its use in Grails (which is expected, since it's not that common a requirement). It's not well documented, but this bug report highlights some of the potential pitfalls and should still be a working example (the test app is still on GitHub): https://jira.grails.org/browse/GPHIB-6.
I'd like to ensure that this is working and continues to work, so please let me know via email if you have issues later. It's a great feature and having it in Hibernate core makes things a lot easier for us. But we need to make it easy to use and well-documented, and that will happen a lot faster when it's being used in a real project.

Should we be reusing JPA entities

Currently I am working for a company that has 6-7 Java EE projects. They are multi module maven projects that are all fairly large and serve different purposes. As such, their models are very different but for the most part the data is stored in the same database.
The problem, to me, is that since there are a few areas of overlap, they simply inject the existing DAOs all the way up the depedency chain. So I have
A-parent
-A-JPA
-A-DAO
B-Parent
-B-JPA
-B-DAO
-A-JPA
-B-DAO
etc, etc. They are really only using 2 percent of the other projects model and respective DAO.
I am trying to attempt to decouple these dependencies by simply duplicating the entities needed (and only including fields/mappings for the things that are really needed) so that the same EJB isn't deployed 7 times (or more when clustered), but apparently I'm not making a convincing argument. Can anyone help point me to an article with best practices for this situation or help bring up points to explain to him.
TLDR: I want each project to have its own set of entities even if there is a very small bit of overlap to reduce dependencies between projects as well as make it so we aren't deploying the same EJB's 7 times. My boss thinks there is nothing wrong with these being unnecessarily coupled. Am I making a big deal about this for nothing? Thanks!
If it is a single data model that is being maintained for various applications to use, the persistence entities (and even their DAOs) may be seen as the Java API to that database, and I'd put it in a central component. Some organizations may even drive the design from the database upwards, and reverse engineer the persistence entities, in which case they'll be same or similar for different users.
Whether such central component is a library (reused by other components) or an EJB of its own (that's being called by other components) I would let depend on the desired transactional and caching behavior of the application, and how you see responsibilities being organized. On one project we strongly upheld the rule that each piece of data could only be maintained by a single component (a service or an EJB) and others would have to go through that single component.
If it is a common domain model, but every EJB implement its own data storage for that, then the domain model may be shared, and I would not share the persistence entities. Then you get into the discussion of sharing the domain model among different components. The world may be viewed in slightly different ways from within different sub-domains and I feel that you end up designing your domains slightly different across different sub-systems, hence there I would possibly vote against reuse.
Everyone's mileage may vary, and I may see things differently given the actual circumstances of a particular project.

Recommendations on providing integration api

Are there any recommendations, best practices or good articles on providing integration hooks ?
Let's say I'm developing a web based ordering system. Eventually I'd like my client to be able to write some code, packaged it into a jar, dump it into the classpath, and it would change the way the software behaves.
For example, if an order comes in, the code
1. may send an email or sms
2. may write some additional data into the database
3. may change data in the database, or decide that the order should not be saved into the database (cancel the data save)
Point 3 is quite dangerous since it interferes too much with data integrity, but if we want integration to be that flexible, is it doable ?
Options so far
1. provide hooks for specific actions, e.g. if this and that occurs, call this method, client will write implementation for that method, this is too rigid though
2. mechanism similar to servlet filters, there is code before the actual action is executed and code after, not quite sure how this could be designed though
We're using Struts2 if that matters.
This integration must be able to detect a "state change", not just the "end state" after the core action executes.
For example if an order changes state from In Progress to Paid, then it will do something, but if it changes from Draft to Paid, it should not do anything.The core action in this case would be loading the order object from the database, changing the state to Paid, and saving it again (or doing an sql update).
Many options, including:
Workflow tool
AOP
Messaging
DB-layer hooks
The easiest (for me at the time) was a message-based approach. I did a sort-of ad-hoc thing using Struts 2 interceptors, but a cleaner approach would use Spring and/or JMS.
As long as the relevant information is contained in the message, it's pretty much completely open-ended. Having a system accessible via services/etc. means the messages can tap back in to the main app in ways you haven't anticipated.
If you want this to work without system restarts, another option would be to implement handlers in a dynamic language (e.g., Groovy). Functionality can be stored in a DB. Using a Spring factory makes this pretty fun and reduces some of the complexity of a message-based approach.
One issue with a synchronous approach, however, is if a handler deadlocks or takes a long time; it can impact that thread at the least, or the system as a whole under some circumstances.

Should I hide generated classes behind a layer?

I have several classes that were generated from a WSDL and I need to write 2 small applications that read some input data, call the webservice and write the responses.
Right now I created a bunch of very simple wrapper classes that take the data from the objects returned by the webservice call. I created a wrapper around the webservice proxy that returns my own classes instead of the generated types. What I try to aim for is a decoupled model, that will not reveal any of the generated classes to my simple applications.
But I think I may overengineer the whole thing. For now the 2 small applications will be almost the same size as the model classes and wrappers, but I am sure there will be more requirements coming up later and I want to be flexible.
Should I hide the generated classes (and think about this part as a Data Access Layer) or should I go with the generated classes for the first version?
We are talking in generals here, so I will respond in kind. Unless you have specific requirements that you are building to, don't engineer for the future too much, other than choosing frameworks and methodologies that can be flexible for the future. The thing is, if you engineer for the future now, you don't even have the requirements nailed down so you are working on guesses and worries. See the "You Ain't Going to Need It" principle.
Now for the question of wether you need the Data Access Layer now: if you find that you have a layer that does nothing but translate between two other layers, you don't need it. If, on the other hand, there are a set of tasks that if handled in a layer that will make other layers more concise and clear, hopefully all while reducing redundancy, go for it.

Categories

Resources