I have already written one web app using java,spring, and tomcat8 as server and now I want to write other but this one has to interact with the previous. It has to share some data from database and session(I mean if user login in one app he doesn't need to login in other app). What is the best way to implement this ?
There are a couple of ways to solve this. Tomcat supports clustered see: https://tomcat.apache.org/tomcat-9.0-doc/cluster-howto.html
But as Dimitrisli already wrote it may be the easiest solution to have a look at spring-session (see: http://projects.spring.io/spring-session/).
I am using this in a project of mine and it works pretty good, but you have to be aware that right now the default serialization scheme is "ObjecStream" which is the regular java serialization. So you can't use different versions of a class on your servers that you are putting into the session. This would lead to a deserialization exception. But I am pretty sure the same problem may occur if you use tomcat/jboss7glassfish/etc. clustering.
If you want to be free in your service deployments, you may use one of the clustering solutions and only store the minimal information that is necessary, like the sessionID and then use something like redis or whatever DB solution you like to store the session related data in a more "class-evolution" friendly format like for example json. This leads to more work for you, but also much more flexibility.
This is fairly broad, but generally speaking, you'd just use the same database configuration for both applications, and you can use session replication to share sessions between servers. Tomcat has some built-in functionality to do that, but you should also consider Spring Session, which hooks into the servlet filter chain to externalize sessions in a cross-platform style.
There are a few solutions for session clustering but since you are in the Spring ecosystem take a look at the newly launched Spring Session project which makes this task much easier and is also webapp provider agnostic.
Generally sharing sessions is not recommended, for database sharing use JNDI and get the objects. If login is to be handled in your case use Single SignON.
Related
If I have a distributed java web application deployed in a cluster and I have say 10 servlets & 10 JSPs running the show, and if I want to share some data, say a variable or a simple POJO between all the threads of all the servlets on all the machines, what is the way to do it?
No framework like Spring/Struts is used and let's say I'm only using the basic Servlets and JSPs. Usually we think about ServletConfig, ServletContext, HttpSession and HttpServletRequest objects to store information which needs to be passed/shared from one component to another. ServletContext has the largest scope because it's accessible from all the servlets and JSPs in the web app. But in case of distributed application I guess ServeltContext object would be created one per JVM, so even for a single web app every machine in the cluster will have a different java object for ServletContext, correct? So in such a scenario what should be done to share a POJO between all the servlets on all the machines of a single web app?
If it's not possible using plain Servlets and JSP, do any frameworks make is possible? Would appreciate any inputs. Many thanks!
In a distributed architecture, it is useful to think beyond objects and think about "services". There are several possible solutions for this but all of them would include some form of service you could access from any of your 10 nodes.
So, you could for example create an 11th machine and host an API for putting and getting objects (values/maps/etc?). That would create a shareable region between the nodes.
However, this opens a whole world of possible issues if not done correctly, because you need to think about sinchronization, deadlocks, dirty reads and other concurrent processing stuff in a cross-JVM mindset.
Also, many systems sinchronize their nodes via the database, but this approach is somehow deprecated nowadays in favor of the more recent "microservices" approach where persistence is distributed, not monolithic.
you are using spring already, so maybe spring session project is a right choice for you - http://projects.spring.io/spring-session/. For sure its the easiest one to run.
You can use hazelcast, a framework as memcache but with auto-discovery for clustering . I use to used for the session and cache sharing on my Amazon cluster and works like a charm
http://hazelcast.com/use-cases/caching/
But if you want keep in simple you can always use as I said before memcached
http://memcached.org/
Sharing things between servers is:
error prone
sometimes complicated
The most common thing to want is user session data across a load balanced cluster of servers. If someone is talking to one server, then gets load balanced to a different server, you want to keep their session going. Tomcat Clusters does this, and it's already built in.
https://tomcat.apache.org/tomcat-7.0-doc/cluster-howto.html
The last time I played with that, it was touchy; don't count on session replication always working in any servlet container, and you'll be better off. Also, session replication is crazy expensive; once you're past a few machines, the cost (in RAM) of having all session data everywhere... starts to add up quickly, and you can't add more users easily anymore.
Wanting to share things between multiple JVMs is a code smell; if you can architect around it, do so. But other than clustering, you have the two normal options:
a database. Tried, true, tested; keep details that need to change there.
an in-memory store. If it gets called on every request, and/or must be really fast for whatever reason, just consider keeping it in memory; memcached is a multi-machine in-memory key-value-store that does just this.
The simplest solution is ConcurrentHashMap https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html
If you want to scale your application - you will need something like hazelcast - http://hazelcast.com/
We have an existing large Java Web Application that is clustered across many servers. We currently store our Word documents within our Oracle/BLOB and would like to move to a CMS solution like Liferay. Ideally we would like to present our users a view of their directory/file within one of the pages of our existing application and implement some workflow on top of Liferay within our application.
I've been reading the Liferay documentation to get a good feel to how best integrate into an existing Liferay/CMS server and from what I can tell the only way is via Portlets and or IFrames. So the integration happens in the GUI of the application.
We were hoping to integrate with Liferay within our Server calling SOAP/REST/JSON calls and then taking the results and displaying it within our application.
Could someone educate me on if this is feasible and if it is where I could get further information regarding this?
Yes, you can integrate just at "view side", but a good choice consists in usign Liferay ServiceBuilder.
It is a well documented Liferay's framework available for any custom portlet you want to write, allowing you to:
- automatically create a ready-to-use persistence layer (db DDL, ORM, cache configuration, transaction ecc...)
- expose local (in the same VM), remote (in the same VM, or by SOAP/REST/JS API/Mobile API) functionalities
You can surely combine both functionalities together, but you are free to use just one of them.
If it was a my choice, I would create a LR service wrapping the call to your external datasource.
In this way it will be able to partecipate in a distributed transaction (simply configuring a distributed transaction manager), to configure access to resource by using LR permissions framework, to be compliant with any kind of LR taglib (as SearchContainer: it should be very useful for showing a list of item)... and everything without the necessity to configure anything.
Several ways for achieving what I said are available... with a simple Google search I immediately fiund this guide.
Hope it helps.
Liferay allows you to write your own custom document store. You will need to implement few interfaces and configure LR to use it. That should do it. You can look at com.liferay.portlet.documentlibrary.store.BaseStore and com.liferay.portlet.documentlibrary.store.DBStore to understand how it can be done.
Thanks
I'm coming from a full application server background and considering running apps on a lightweight embedded server such as Jetty.
I've always used JNDI to look up connection pools for things like database connections but I'm wondering whether that's the best approach for the lightweight case. It seems that if I use JNDI I don't get anything beneficial, but I do get variation in how different containers are configured and additional complexity in setting up.
The alternative I can see is just embedding a connection pool implementation in my app. As I use Spring, this approach has a little less configuration required, what configuration is needed is all in one place (with the ability to look up simple name-value properties such as connection details from elsewhere if needed) and would seem to work regardless of the context (dev/test/live) and what container I deploy with.
Am I missing something here? Should I still use JNDI if I am embedding an application server in my application? If so, why?
It depends entirely on your situation.
JNDI (to me) is a mechanism to achieving a decoupling between what your deploying and where you are deploying it. Such that when you are deploying you are assuming certain resources will be available and they are going to be labeled X, Y and Z. JNDI is the simple (kinda) mechanism to provide those resources in a basically uniform way. If your going to have potentially multiple different supported databases and you want to write all your code against some data source...your going to need that datasource configured somewhere and jndi gives some place to do it. If your using some sort of tooling that makes setting up jndi a cakewalk, then great, use it.
In an embedded situation the circumstances really don't change, things still need to be setup somewhere. However, in the course of your embedded application you find yourself writing both sides of the jndi equation, then do ask yourself if you need this extra layer of abstraction.
If your just using jndi because that is whatever everyone else does, but you only use postgres really and you just need that database driver...then what is the point of the extra layer of complexity for your application. If you really like spring and spring gives you an easier way of configuring the bits and pieces you needs and injects it where you need it...don't use jndi.
fwiw, it kinda sounds like you don't need jndi anymore :)
I am looking around for a multitenancy solution for my web application.
I would like to implement a application with Separate Schema Model. I am thinking to have a datasource per session. In order to do that i put datasource and entitymanger in session scope , but thats not working. I am thinking to load data-access-context.xml(which include datasource and other repository beans) file when the user entered username and password and tenantId. I would like to know if it is a good solution?
Multitenancy is a bit tricky subject and it has to be handled on the JPA provider side so that from the client code perspective nothing or almost nothing changes. eclipselink has support for multitenancy (see: EclipseLink/Development/Indigo/Multi-Tenancy), hibernate just added it recently.
Another approach is to use AbstractRoutingDataSource, see: Multi tenancy in Hibernate.
Using session-scope is way too risky (also you will end up with thousands of database connections, few for every session/user. Finally EntityManager and underlying database connections are not serializable so you cannot migrate your session and scale your app properly.
I have worked with a number of multi-tenancy systems. The challenge here is how you keep
open architecture and
provide a solution that evolves with your business.
Let's look at second challenge first. Multi-tenancy systems has a tendency to evolve where you'll need to support use cases where same data (record) can be accessed by multiple tenants with different capacity (e.g. https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458). So, the system ultimately needs Access Control List.
To keep the open architecture you can code to a standard (like JPA). Coding to EclipseLink or Hibernate makes me uncomfortable.
Spring Security ACL provides very flexible community supported solution to both these challenges. Give that a try. I did and been happy with it's performance. However, I must caution you, it took me some digging to get my head around it.
I am creating a web site in which user will be registered and he/she will be redirected if he/she has account.
So I was thinking to use servlet to link form and database.
Is it safe to use from hacking.?
Which is the best language which has less chances to get hacked than servlets ?
Well I am quite exicited to create it but I really don't want hacking my site very easy task.
As long as you are using Java for web forms, at some point any framework you use is based on servlets. So if you use them properly, yes it is safe.
The main point to keep in mind to prevent cracking your authentication (if database based) is SQL injection. As long as you use Hibernate, JPA or prepared statements you should be safe.
If using Tomcat, you can also start with Tomcat native authentication.
Just like any other framework, it's reasonably safe from hacking and not totally immune. You will be vulnerable to:
mistakes in your code/logic;
vulnerabilities in Tomcat/your servlet runner as they are discovered;
vulnerabilities in the JVM as they are discovered;
vulnerabilities in the OS;
vulnerabilities in... well, you get the idea...
In other words, it's essentially not so different anything else you might decide to use (be it PHP etc). I personally prefer Java to e.g. PHP because I have more confidence that there isn't some random default setting that's going to put the app at risk. But that's also because I'm far more of an expert in Java than PHP-- "use the technology you know best" is also another strategy...
Main things to keep in mind, apart from keeping your infrastructure updated:
don't use "raw" SQL to access the DB: at least use prepared statements, and for good measure implement some sensible validation on user input;
look at the Servlet Session API;
you generally want to check the logged in user for every page request: not sure exactly what you meant by "redirection";
if possible, firewall off "raw" access to the database, so that only localhost/the app server (if hosting DB on a separate server-- guess you won't to start off with) can access your DB (if you need to access remotely, consider a VPN connection).
I also wouldn't necessarily just "dive in": have more of a read round the subject.