To JNDI or not to JNDI when embedding an application server? - java

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 :)

Related

Java EE web applications and environment configuration

Hello stackoverflow Users,
I have found myself working on a Java EE Web Application and I know for a fact that my application is going to be deployed into multiple environments. Each environment may have slightly different configuration of some features, e.g. remote web-service URLs. Additionaly, I would like - if possible - to have the following 2 properties met:
Per environment config should not in web-application repository
This is because I feel it does not belong there. I would not want to manage n-configurations next to my source code. Moreover, if there are secrets there, I would not want every developer to see them...
Enforce completeness of configuration
If I say that I need a certain configuration parameter/resource then it would be meaningless if it was not provided. I would not want my application to start in such case.
Please, can somebody more knowledgable and experienced help me and nudge me into the right direction?
My findings so far
Naturally, I have spent some time searching the answer already ...
Spring framework
I know that spring provides an Environment class as an abstraction of environment-specific configuration. However, I am not using Spring framework, nor does it describe how to put this configuration outside of the web applicatoin.
Java EE JNDI Service
According to the Java EE platform specification, the right way to do it would be to use env-entry, resource-ref and resource-env-ref elements in my WEB-INF/web.xml and have them bound/set to values in the web app container configuration.
This actually sounds very good, except that I don't know how to enforce the completeness of this configuration. I mean, I declare the above mentioned elements, to tell the deployer that I need them, yet I see (tested on tomcat) that application still deploys (and works incorrectly) when some, say resource-env-ref, is not bound.
I don't know how to achieve it tbh, however, if there is nothing better, it still feels like the best thing I could find. :-|
I have taken the JDNI approach.
I have added validation of configuration by introducing a custom ServletContextListener implementation.

Two webapps which share data and session

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.

In a distributed Java web application, how to share a value between all servlets on all machines?

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/

How to deal with databases for websites written in Java, more specifically Wicket?

I'm new to website development using Java but I've got started with Wicket and make a little website. I'd like to expand on what I've already made (a website with a form, labels and links) and implement database connectivity.
I've looked at a couple of examples, in example Mystic Paste, and I see that they're using Hibernate and Spring. I've never touched Hibernate or Spring before and to be honest the heavy use of annotations scare me a little bit as I haven't really made use of them before, with the exception of supressing warnings and overriding.
At this point I have one Connection object which I set up in the WebApplication class upon initialization. I then retrieve this connection object whenever I need to perform queries. I don't know if this is a bad approach or not for a production web application.
All help is greatly appreciated.
Wicket, Spring and Hibernate is pretty much the standard stack for Wicket applications. Or let's rather say that any web framework, Spring and Hibernate is pretty much the standard stack for any web framework.
Regarding Wicket, injecting objects using #SpringBean inside components is an extremely nice to have feature. Additionally, the OpenSessionInViewFilter manages Hibernate sessions for you (while Hibernate itself takes care of connections).
Therefore, I'd really suggest you look into Spring and Hibernate - both of which don't require annotations, but they are most of the time easier to use than configuration files (typically XML).
If you still don't want to use Spring or Hibernate, I'd suggest you look at the OpenSessionInViewFilter and create something similar yourself: create a connection for each request, use it during one request, close it at the end. As this won't perform very well, you might rather choose to get connections from a pool to which you return it at the end of a request. But instead of writing this code, you could already be injecting beans into your components ;)
Bad approach because a Connection object is intended for use by a single thread and web application requests are processed from a pool of thread.
In the best case you'll suffer for big performance problems cause the connection object won't execute queries concurrently.
A solution to this problem is the usage of a connection pool.
If you have time you can dig around Apache Cayenne, it's far more light than Hibernate and for dependency injection combine with Google Guice, again very lightweight. Wicket has wicket-guice subproject, which provides DI in wicket components, much like Spring Context.
IMHO it's fair alternative, works very nice so far.

Java Application/Thread Server

I am looking for something very close to an application server with these features:
it should handle a series of threads/daemons, allowing the user to start-stop-reload each one without affecting the others
it should keep libraries separated between different threads/daemons
it should allow to share some libraries
Currently we have some legacy code reinventing the wheel... and not a perflectly round-shaped one at that!
I thought to use Tomcat, but I don't need a web server, except maybe for the simple backoffice user interface (/manager/html).
Any suggestion? Is there a non-web application server, or is there a better alternative to Tomcat (more lightweight, for example, or easier to configure)? Thanks in advance.
Have you looked at OSGi ? You can load/unload bundles (basically .jar files with metadata) independently of each other, and optionally define dependencies between these (with a software lifecycle defined such that bundles are aware of other bundles being loaded/unloaded).
I have found the Jetty "contexts" concept very useful in handling applications (packaged as WAR's and with servlet context listeners), where the xml-file placed in contexts/ describe fully what you want to have started. When you remove the xml-file again, the thing described is stopped.
If you do not start a server connector you will just have a start-stop thing which sounds like what you are looking for.
Jetty can be made very small so the overhead is not bad.
You could consider Spring dmServer. It's a rather non-traditional appserver, with a very lightweight OSGi core (the web container is optional, for example), but it gives you classloader isolation and basic container services. It's not a JavaEE container, but comes with plug-in modules that are.
You're stlll going to have to do a lot of work yourself, but the basics of dmServer are very sound.
No one stops you from sending binary and text data instead of HTML-pages using http protocol. That is whats servlets are for. So I would use the tomcat server.

Categories