Java Swing - Single user application to a Multi user application - java

I am a newbie......I have a Java Swing application and it runs great on my machine. I want to access this application from a Server via Citrix. So when I click on the published icon, it would run the main method in the jar file and will enable me to access the application. This application will be able to access a DB in the DB Server.
But I want mutliple users to access the application at the same time and that is where my questions are:
I thought of creating n number of threads available for n number of users (i.e.) I can set a limit on concurrent access. But what will be the entry point.....I mean when I click on the published icon, it means each time the main method will be invoked.
I can think of seperating my User Interface from the Logic layer....but I have no idea how to do it. ofcourse I am following MVC model. My question is in terms of creating multiple instances of the gui each time the application is accessed.
And finally I want to use DB Connection pooling. So, would this mean that I have to create a separate java program that creates this pool and my application will use its datasource?
Can anyone please 'point' me in the right direction? I am not looking for specific ideas but just an idea on how to create this multi user application.

Typically, for a multi-user Swing application you would want to separate the "client" part of the application from the "server" application.
This works as follows:
Each user would get their own running instance of the client application. This can be on their own machine.
The server application is a single instance (or maybe a cluster) that accepts connections from multiple clients and talks to the database
The client applications talk to the server application when they need to access or change data. There are a wide variety of different communication methods you can use.
Optionally, the server application can send notifications to the client (e.g. in situations where data is updated by another client)
You can do without the server application if you are happy to let the clients connect to the same database. This is simpler to set up, but has some downsides:
You need to be much more careful about concurrent access to the database / potential corruption from different clients attempting to alter the same data at the same time.
You need to allow connections to your database, from clients that are potentially untrusted. This is a security risk.
Given that you already have a working application, the second option is probably easier for you to move to. Just be aware of the downsides: the first option is a much better architecture in general.

Related

Server Storage - Java

I have the following problem: I have Java application - Sprint boot, which uses Angular in the frontend. This application needs to store some data on the client side, however, this data is lost when the client changes their browser or opens an anonymous browser tab.
I need an alternative, other than linking data to the user in the database. Something that is implemented in Java itself.
Is there any way I can store data in Java - Even though I know they will be volatile, that is, we can assume that my application server will be up 100% of the time.
**edit
My server run a openshift plataform that have multiple pods, the load baancer of server are configured in a NON-Sticky sessions design. That's why we can assuming that my server will be 100% active.
This really depends on the design of your server. For example, why is it guaranteed to be up 100% of the time? Do you have multiple redundant instances? In that case you need to coordinate that "storage" between all instances; you may even want to deal with a quorum of instances keeping the state etc. Doesn't seem to be trivial. Or do you have just one single instance? But how do you guarantee 100% uptime?
I strongly recommend using some kind of data store or at least distributed cache.

Singleton pattern is produced some problems when there are some updates

We have an Oracle database which hold data about some cities and
places, etc.
We have a web system which we can manipulate these datas.
We also have a desktop client application which is working with these
data.
For increasing our desktop application performance and decreasing unuseful request for our DAO layer, we have implemented some Singleton classes in our desktop application to fetch mentioned cities, places, etc data only once right after the user is opened his/her desktop application.
Recently we received a request from our clients why we don't see the changes we make using the web application, when the client desktop application is live and up and running. They're complaining about why they have to close the desktop app and open it again in order to see the changes.
We know that the problem is those Singleton classes but we don't want to change them because it's gonna be huge overhead in our system when they're not there. For solving the problem we have thought about multiple solutions:
Create a table in a database with integer column names similar to our data columns (cities, places, etc) and auto increment value when there's an update for tracking the changes using it (a light weight solution)
Using database functionalities
a Notify system that notify the client application whenever an update occurred.
a caching mechanism inside database that cache those lately changing tables and service our users when they have similar request
Here are our stacks:
Our Desktop application is swing application
Our Web application is JSF
Our business layer for both JSF and swing is EJB
Our Dao layer for both JSF and swing is Eclipse-Link
What do you think is the best practice for solving this problem ?
Oracle has a feature called "Database Change Notification" that can be used to be notified when read-mostly tables are changed. It looks like this feature could be a good fit to address your requirement. The link to the doc is here.
In a nutshell, the way it works is that JDBC thin driver in your desktop application would open a port and the Oracle Database would connect to that port and use this connection to push notifications when data changes. You then get a callback through an event/listener API and can refresh your cache.
This notification mechanism is designed for data that is read-mostly, in other words, data that doesn't constantly change otherwise it wouldn't be worth caching the data anyway.

Any properties needs to be changed for multi user application

Please consider me as a novice and this is my first web app I am creating.
I am planning to develop a web application where the traffic I am expecting is around 50 users will access the application at a single time.
The webapp is developed with Vaadin (for UI) and respective business logic implemented with Java. DB used would be MySQL. The war will be deployed in Tomcat.
So, my question is do I need to modify anything in Tomcat properties or anywhere to make the web app as multi user application (i.e. each users need to access and use application as though they are only one using the application)?
I tried to access a prototype developed using Vaadin in both Chrome and Firefox and could see both sessions running without an impact on another.
But please let me know suggestions.
You must keep in mind that even if tomcat and vaadin manage multiple sessions, your server application will have only 1 instance. So if you use singletons, static methods or fields, use them with care: they should never hold session-dependant content. Try to favour stateless methods over statefull.
Apart from that, there shouldn't be any problem.
It should not have any code changes if you handle the session and your business logic with statefulness properly.
There might be some configuration changes, like increasing the database connection pool size, it depends on what kind of connection pooling you are using and what is the default size etc.
Apart from that it should work just fine.
Vaadin is built on top of Jakarta Servlet technology (formerly known as Java Servlet). See Wikipedia. Indeed, Vaadin is a servlet, a much bigger and more sophisticated servlet than most.
Within a Java Servlet container (engine) such as Apache Tomcat or Eclipse Jetty, any particular servlet has only a single instance running. If three requests from three users arrive at the same time, there are three threads running through that same single instance for that particular servlet. So a servlets are inherently a highly threaded environment.
If you share any variables or resources between those threads, you must be very careful. That means mandatory reading, rereading, and fierce study of the book Java Concurrency in Practice by Brian Goetz, et al.
While the Web and HTTP were designed to be stateless delivery of single documents, that original vision has been warped by the desire to make web apps. To maintain state, a servlet automatically maintains a session. Vaadin represents this session state in its VaadinSession object. All data in all the forms, along with business logic, running for each user is maintained as part of that session.
Depending on your particular Vaadin app, and when multiplied by the number of concurrent users, this may add to a large amount of memory. You should monitor your server to make sure you have enough available RAM on your server.
do I need to modify anything in Tomcat properties or anywhere to make the web app as multi user application (i.e. each users need to access and use application as though they are only one using the application)?
No, nothing for you to set or enable. Tracking the requests/responses and session for each user is the very purpose of a servlet container. From the moment it launches, every servlet container expects multiple users. As a Servlet, Vaadin is built to expect multiple users as well. The only trick is making your own code thread-safe, hence the book suggestion.
I tried to access a prototype developed using Vaadin in both Chrome and Firefox and could see both sessions running without an impact on another.
Concurrency problems can be very tricky to detect and debug. Often potential problems occur on the random chance of coincidental timing. You need to focus on properly designing your code in the first place, rather than relying on testing. Again, hence the book recommendation.
Of special note, since you mentioned using a database, is JDBC drivers. Deploying them in a Servlet environment can be tricky. Basically you need to not bundle them within your Vaadin web app WAR file. Instead, deploy the JDBC driver separately within a shared library folder within Tomcat. If using Maven to drive your project, direct Maven in the POM file to give the dependency for your JDBC driver a scope of provided. This has nothing to do with Vaadin specifically, it applies to all servlets. Search Stack Overflow as this issue has been extensively addressed.

Single virtual tomcat application which serves multiple contexts

I have multiple clients:
client 1 - 40 users
client 2 - 50 users
client 3 - 60 users
And I have a web application that is supposed to serve all the clients.
The application is deployed into Tomcat. Each client has it's own database.
What I want to implement is the single web application instance which servers all the clients. The client (and the database to connect to) is identified by the context path from the URL.
I.e. I imply the following scenario:
Some user requests the http://mydomain.com/client1/
Tomcat invokes a single instance of my application (no matter which context is requested)
My application processes the rest of the request thinking that it's deployed to /client1 context path, i.e. all redirect or relative URLs should be resolved against http://mydomain.com/client1/
When the client 2 requests the http://mydomain.com/client2/, I want my application (the same instance) now process it just like if it was deployed to /client2 context path.
Is this possible with Tomcat?
Your application has to do this not tomcat. Now you could deploy your application in three new contexts (client1, client2, client3) with slightly different configuration for the database, and if you are careful to use relative URLs (ie don't do things like /images) then you can do this without changes. This is the transparent way of making your application reusable in that your application is unaware of the global picture that you have 3 different instances of itself running. That means you can easily deploy more or more without having to change your application. You just configure a new instance and go. This only requires you don't use absolute URLs to resources. Using ServletContext.getContextPath() and using .. in your CSS, scripts, etc is helpful as well here.
Probably one of the biggest advantages working this way is that your app doesn't care about global concerns. Because its not involved in those decisions you can run 3 instances on one tomcat server, or if one client needs more scaling they can be moved to their own tomcat server easily. By making your app portable it has forced you to deal with how to install your app in any environment. This is a pillar of horizontal scaling which your situation could very much take advantage being you can split your DB data without having to rejoin them (huge advantage). The option you asked about doesn't force you to deal with this so when the time comes to deal with it it will be painful.
The other option is more involved and requires significant changes to your application to handle this. This is by parsing the incoming URL and pulling out the name of the client then using that name to look up in a configuration file for the database that should be used for that client. SpringMVC can handle things like extracting variables from URL paths. Then making sure you render everything back to them so it points to their portion of the URL. This probably would require a lot of the same requirements as the first. You can use absolute URLs for things like javascript, CSS, and images, but URLs to your app would have to be rewritten at runtime so that it is relative to the requesting client. The benefit is that your only load your application once.
Just as an aside, if you host your CSS, Javascript, images on a CDN in production then both of these options must be relative URL aware. Upsides and downsides to using CDNs as well.
While that sounds good it might not be a good thing because all clients use the same version of the app. Also if you bring down a the app to fix client1 to do maintenance it affects all clients. If you think you'll have to do customization per client then this option will get messy quick. Upgrading a single client means all clients must upgrade and depending on your business model this might not be compatible. Furthermore, I'm not entirely sure you'll save a lot of memory either running only a single version of the application because most apps only take up 10MB of code loaded. A vast majority of the memory is in the VM and processing requests, and using a single Tomcat instance means you share the VM. And with 1 or 3 instances running you still have the same number of requests. You might see a difference of 30-100MBs which in todays world is chump change, and all of those other concerns aren't addresses if you choose to save only a couple of MB.
Essentially there are facilities in Tomcat to aid you in doing this (multiple contexts), but its mostly up to your application to handle this especially if its a single instance.

Two different Java applications sharing the same database

In my web application I have a part which needs to continuously crawl the Web, process those data and present it to a user. So I was wondering if it is a good approach to split it up into two separate applications where one would do the crawling, data processing and store the data in the database. And the other app would be a web application (mounted on some web server) which would present to a user the data from the database and allow him a certain interaction with the data.
The reason I think I need this split is because if I make certain changes to my web app (like adding new functionalities, change the interface etc.) I wouldn't like the crawling to be interrupted.
My application stack is Tapestry (web layer), Spring, Hibernate (over MySQL) and my own implementation of the crawler independent from the others.
Is it good for the integration to be done just by using the same database? This might cause an issue with accessing the database from the both applications at the same time. Or can the integration be done on the Hibernate level, so both applications could use the same Hibernate session? But can the app from one JVM instance access the object from another JVM instance?
I would be grateful for any suggestions regarding this matter.
UPDATE
The user (from web app's interface) would enter the URLs for crawler to parse. The crawler app would just read the tables with URLs the web app populates. And vice versa, the data processed by the crawler would just be presented on the user interface. So, I think I shouldn't concern about any kind locking, right?
Thanks,
Nikola
I would definitely keep them separated like you are planning. The web crawling is more a "batch" process than a request driven web application. The web crawling app will run in its own JVM and your web app will be running in a servlet/Java EE container.
How often will the crawler run or is it a continuously running process? You may want to consider the frequency based on your requirements.
Will the users from web app be updating the same tables that the crawler will post data to? In that case you will need to take precaution otherwise a potential deadlock may arise. If you want your web app to auto refresh data based on new inserts in the tables then you can create a message driven bean (using JMS) to asynchronously notify the web app from the crawler app. When a new data insert message arrives you can either do a form submit on your page or use ajax to update the data on the page itself.
The web app should use connection pooling and the batch app could use DBCP or C3P0. I am not sure you gain much benefit by trying to share the database sessions in this scenario.
This way you have the integration between the two apps while not slowing down each other waiting on other to process.
HTH!
You are right, splitting the application into two could be reasonable in your case.
Disadvantages of separating into two applications -
You can not cache in Hibernate or any other cached mutable objects that are modifiable from both applications in any one of them. Optimistic locking should work fine with two hibernate applications. I don't see any other problems.
Advantages you have already specified in your code.

Categories

Resources