Spring Boot | Use dynamic keystore/truststore - java

I need to use dynamic keystores in my Spring Boot application because at any moment i might have to change them and i don't want to have any downtime.
From what i saw it this post i have three options:
Writing a custom KeyManager;
Use a reverse-proxy;
Or on Tomcat use local JMX to reload SSL context.
In last one i don't really understand the implications of that. The reverse-proxy seems the easier way, but is it the best approach?
If someone could point me which one would be the best solution and why or recommend something else would be much appreciated.

You can have your own implementation of SslStoreProvider which will enable you to get the keystore/truststore from whatever source you want (does not need to be on disk).
Then check out #RefreshScope you can recreate beans (like your own SslStoreProvider) with it.
Here you can find an example (please note that this was only created to demonstrate a bug in spring-boot 1.x which was fixed in 2.x).

The external reverse-proxy approach is the most flexible. It doesn't require any changes to your application or deployment logic and will address most of the scenarios. The downside is that your architecture gets more complex and requires additional server resource for the proxy server.
You can take it a step further and do blue-green deployments:
The blue-green deployment approach does this by ensuring you have two production environments, as identical as possible. At any time one of them, let's say blue for the example, is live. As you prepare a new release of your software you do your final stage of testing in the green environment. Once the software is working in the green environment, you switch the router so that all incoming requests go to the green environment - the blue one is now idle.

Related

What is a better way to change variable in runtime server?

We maintain our server once a week.
Sometimes, the customer wishes that we change some settings which is already cached in server.
My colleague always write some JSP code to change these settings which are stored in the memory.
Is it a good method to use this kind of methodology?
If our project is not a Web container, which tools can help me?
Usually, in my experience, the server configuration is not stored only in memory of server:
What happens that after a configuration change, the server has been restarted / just went down for some system reason?
What happens if you have more than one instance of the same server to work on (a cluster of servers in other words)?
So, usually, people opt for various "externalized configuration" options that can range from "file-based" configuration + redeploy the whole cluster upon each configuration change, to configuration management servers (like Consul, etc.d, etc). There are also some solutions that came from (and used in) a java world: Apache Zookeeper, Spring cloud config server to name a few, there are others. In addition, sometimes, it's convenient to store the configurations in a database.
Now to your question: If your project is not a web container and you don't care that configuration will "disappear" after a server restart and you're not running a distributed cluster of servers, then, using JSP indeed doesn't seem appropriate in this case.
Maybe you should take a look at JMX - Java management extensions, that have a built-in solution so that you probably will be able to get rid of a web container (which seems to be not used by your team anyway other than for JSP modifications that you've described).
You basically need in memory cache, there are multiple solutions found in answers which include creating your own implementation or using existing java library. You can also get data from database and add cache over the database layer.

Share object between JavaEE applications on the same JVM (using JNDI)

I'm running a JBoss AS 7.1.3.Final installation with a lot of applications. One of those applications provides common resources and functionallities used by all applications (let's call it framework). I'm also planning to move to WildFly 8, if this is an useful information for your answer.
All applications should only be accessible, if the framework is available (up and running). My current implementation to achive this dependency is not that nice** and as I'm currently re-designing some parts of the environment, I'm looking for a much neater solution for it. My first idea was to create some kind of a manager which will be instantiated by the application server and is available to all applications. So after an application is started, it could register itself on the manager and as soon as the framework is up, the applications will be notified.
Is this possible using the JNDI of the JVM where all applications + framework are running? How must this be implemented? It's really hard to find useful information about how the JNDI works and what is possible with it. Do you have any other, simplier ideas, how to share a class instance between applications?
Thank you.
** Currently I'm using a EJB-timer in the applications and a singleton EJB in the framework. The framework is available as soon as the EJB lookup succeeds.
--
Edit #1
Some more informations as requested by Nikos Paraskevopoulos
One functionionality that is provided by the framework is the maintenance mode. The applications will check, right after startup, if it is blocked for normal users. It will also receive notifications about planned maintenances. (central DB, the application has no rights on it)
Common stylesheets or layouts are deployed with the framework.
The user informations are provided by the framework. (central DB, the application has no rights on it)
The main problem is: How could I avoid any timers? I have no idea, how I could ensure, that the framework is up before everything else.
A few thoughts:
JBoss has the capability of ordering deployments according to their dependencies. See here and here. So, if all the "applications" depend explicitly on the "framework", your problem may be solved.
It seems you have a quite strongly coupled configuration. Would it be possible to decouple them, e.g. provide the service through web services (SOAP/REST)? Of course this introduces extra overhead for the communication and the refactoring...
JNDI can be seen (very roughly) as a name to object map shared across the applications. As such, you may share stuff through it. But I do not see how will you solve the timing problem, i.e. wait for a service to be available before using it from the "applications". The manager component you mention can be placed in JNDI.
This is not a complete answer, but it would not fit as a comment either. Maybe if you presented more details on the nature of the applications, the frameworks used etc, you could get more specific answers.
Good luck anyway
Edit #1:
Maintenance mode: This may be nice for using with JNDI. A servlet filter that intercepts every (applicable) request will check a global JNDI name; if it is not found (i.e. framework not started) or it is false, it will short-circuit the processing of the request, sending back the "maintenance mode" page. The framework will have to set a Boolean in the global JNDI name as soon as it has started and maintain its value, i.e. set it to false if maintenance mode is active.
Common stylesheets: This is really covered by the maintenance mode flag, I believe. Layouts: It depends on the view technology/layouts technology.
User information: This is a good candidate for SOAP/REST implementation. It is not expected to be called frequently, so I assume overhead will not matter.
I think OSGi is the technology you should consider. Basically you have an OSGi container with applications (called bundles) which provide or consume services. So you would have a framework service which is consumed by all applications. JBoss is an OSGi container, as far as I know.

Is it possible to build a web application as a generic product rather than a one-time customized solution?

There is a business problem that needs to be solved. The obvious solution is an enterprise web application - a locally hosted website that provides the desired functionality.
I want to build this web application, but build it such that -
Its more of a product than a one-time solution; such that it can be customized for different clients
It is possible to provide 'fixes' for this web application, so that bugs can be removed and enhancements added with minimum impact on operations
The web app should be capable of working with different databases and existing authentication systems
Is this even possible? Is it a common enough approach that there is a known way of going about this? Would it be better to use an application framework like Spring or try and keep dependencies on frameworks to minimal?
Also, any links or references to books that will guide me will be greatly appreciated.
Thanks in advance StackOverflow!
(I feel like I dont know all what I need to know before embarking on this project, please feel free to point out things I haven't and should consider)
Developing software, esp. for re-usability, requires analyzing which parts/functions are common between use cases and which aren't, drawing the line between re-usable (library) and customized/specialized code.
If you know what use cases you expect or want to support in the future this can be feasible.
If you don't, you should not start trying to generalize arbitrary functionality in the first place, because you cannot know what you will be needing in the future.
Java provides some good abstractions of various functionalities, like universal DB support via JDBC.
If you didn't already, have a look at application servers like JBoss or Glassfish. They provide plenty of basic functionality for web applications, support very loose coupling between components, and are highly configurable. To switch from one DBMS to another, for instance, it is enough to alter a single line of configuration (given the supported SQL is similar enough). Deploying applications or parts can often be done on the fly ("hot deployment") without even stopping the server.
Plus: There is a vast amout of supporting libraries and frameworks out there to help you standardize your application design.
I have been working for a while on a webapp that can be deployed in multiple locations: it is designed to be instantiated on many hosts. It's entirely possible to do this, but it is difficult. Writing the code so that it can work this way takes a great deal of care.
The key to doing it is to make all your dependencies on things explicit and all your configuration driven by properties that can be set during installation. Spring makes this quite a lot easier! In particular, the org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer class allows you to use the servlet context as a source of values that you can then inject into your beans (e.g., via #Value annotations). It's far harder to do all that yourself. Here's (a simplified version of) what I use:
<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
<property name="contextOverride" value="true" />
<property name="location" value="/WEB-INF/default.properties" />
</bean>
This merges the servlet context's properties on top of the ones you provide as defaults inside your webapp (definitely a good practice if most things aren't going to need to be modified most of the time) and then uses them to define properties. I then apply a configuration property (e.g., foo.bar) to a bean property using a placeholder, like this:
#Value("${foo.bar}")
public void setFoobar(String foobar) { ... }
Things to configure that way include the database configuration, absolute locations of files holding things that can't be packaged inside the webapp, etc. You'll have to use your skill and knowledge of the application domain to work out what things need to be listed.
Other key principles are to keep as much as possible inside the webapp (so reducing the opportunity for the deployer to mess it up), to be very careful about documenting everything, and to try it with multiple servlet containers. Remember, the person deploying your webapp does not have access to the contents of your thoughts: you have to write it down and tell them exactly what to do. (Too many instructions are at the level of “click this, click that, magic happens” but those are poor instructions since the exact method will vary over time: saying why will help far more because its more portable.)
We are currently developing a product that can be deployed internally for multiple clients and also as a public portal solution. Here is our experience.
As others have pointed out, there are different factors to keep in mind.
Security
Security that is associated with your product, and how you would manage the product functional requirements to external security roles.
Security, authentication and authorization should not be as part of the base product. Once authorized the roles need to be mapped to product roles for achieving said functionality.
Images and logos, that require customization.
Internationalization.
For working with multiple databases, assuming a product has typically two different views, persistence and querying. Our experience was to use hibernate to support multiple databases, but theoretically we have used only two databases in the past. db2 and mysql.
Testing for multiple databases for every release of your product is a pain. Your test cases goes 3 fold or atleast once in a while to support multiple databases.
Using custom databases and functions are a big no, you can use some general functions but custom database specific functions in your query are going to be a pain and have to be very diligent to avoid them.
Supported browsers in your product.
Licenses of the third party jars may not be compatible / acceptable to all institutions so you have to watch out for that carefully.
As much as possible, enable properties or configuration to customize all variables.
Caching strategy and properties initialization strategies.
A framework helps the team to keep on the same page, rather than an internal framework. There are many advantages to use a well established framework like Spring for performance and other consideration.
Cheers!

Using JNDI for distributed configuration

We're looking at how to do distributed configuration within our primarily Java based deployment. We have a number of applications and it makes sense to centralise the configuration of the applications. JNDI appears to be the standard choice, probably backing off to something like ApacheDS (that way we can store non Java config in there as well). Here are some of the things that I've considered. Has anyone tried something similar? Any recommendations?:
Distributed
This would be for multiple applications on multiple machines, some of the applications would be clustered. The Directory Server should also ideally be clustered.
Lightweight
JNDI has a bit of a J2EE feel to it. Anyone use an alternative distributed configuration mechanism. The applications themselves tend to be relatively lightweight rather than full Java EE applications (ok controversial whether Java EE is still considered heavyweight and requirements are certainly heavyweight).
Supports fallbacks
Often the same configuration applies to multiple applications (e.g. multiple applications may connect to the same database). One the other hand, some applications may need specific configuration. Sometimes it is difficult to know in advance whether an application will use a 'global' configuration or something specific, so being able to first search for application / host specific configuration and then falling back would be good. I'm thinking of a structure something like this:
/global/host/application/instance or /global/application/host/instance:
so, start by checking to see if there is any configuration specific to this instance of the application on this host, then check if there is any configuration specific to this application for this host, then check to see if there is anything specific for this application, then try the global setting. Are there any best practices for this kind of thing?
Live configuration changes
Spring allows configuration with a jee:jndi-lookup and you can choose not to cache the value which means it is looked up each request. I'm not sure that makes sense for "String" type configuration values. It also doesn't appear to use the NamingListener way of detecting changes in the DS. It would be good to be able to update a value on the Directory Server and have that change broadcast to all of the applications that use it.
Other considerations
Managing different environments
Adding the configuration to source control so that it can have change management applied to it
Managing different versions
Rolling back
Have you considered using a database to store the application configuration?
Apache Commons has a DatabaseConfiguration class that exposes your table as a java.util.Properties instance (see http://commons.apache.org/configuration/apidocs/org/apache/commons/configuration/DatabaseConfiguration.html).

What's the best way to share business object instances between Java web apps using JBoss and Spring?

We currently have a web application loading a Spring application context which instantiates a stack of business objects, DAO objects and Hibernate. We would like to share this stack with another web application, to avoid having multiple instances of the same objects.
We have looked into several approaches; exposing the objects using JMX or JNDI, or using EJB3.
The different approaches all have their issues, and we are looking for a lightweight method.
Any suggestions on how to solve this?
Edit: I have received comments requesting me to elaborate a bit, so here goes:
The main problem we want to solve is that we want to have only one instance of Hibernate. This is due to problems with invalidation of Hibernate's 2nd level cache when running several client applications working with the same datasource. Also, the business/DAO/Hibernate stack is growing rather large, so not duplicating it just makes more sense.
First, we tried to look at how the business layer alone could be exposed to other web apps, and Spring offers JMX wrapping at the price of a tiny amount of XML. However, we were unable to bind the JMX entities to the JNDI tree, so we couldn't lookup the objects from the web apps.
Then we tried binding the business layer directly to JNDI. Although Spring didn't offer any method for this, using JNDITemplate to bind them was also trivial. But this led to several new problems: 1) Security manager denies access to RMI classloader, so the client failed once we tried to invoke methods on the JNDI resource. 2) Once the security issues were resolved, JBoss threw IllegalArgumentException: object is not an instance of declaring class. A bit of reading reveals that we need stub implementations for the JNDI resources, but this seems like a lot of hassle (perhaps Spring can help us?)
We haven't looked too much into EJB yet, but after the first two tries I'm wondering if what we're trying to achieve is at all possible.
To sum up what we're trying to achieve: One JBoss instance, several web apps utilizing one stack of business objects on top of DAO layer and Hibernate.
Best regards,
Nils
Are the web applications deployed on the same server?
I can't speak for Spring, but it is straightforward to move your business logic in to the EJB tier using Session Beans.
The application organization is straight forward. The Logic goes in to Session Beans, and these Session Beans are bundled within a single jar as an Java EE artifact with a ejb-jar.xml file (in EJB3, this will likely be practically empty).
Then bundle you Entity classes in to a seperate jar file.
Next, you will build each web app in to their own WAR file.
Finally, all of the jars and the wars are bundled in to a Java EE EAR, with the associated application.xml file (again, this will likely be quite minimal, simply enumerating the jars in the EAR).
This EAR is deployed wholesale to the app server.
Each WAR is effectively independent -- their own sessions, there own context paths, etc. But they share the common EJB back end, so you have only a single 2nd level cache.
You also use local references and calling semantic to talk to the EJBs since they're in the same server. No need for remote calls here.
I think this solves quite well the issue you're having, and its is quite straightforward in Java EE 5 with EJB 3.
Also, you can still use Spring for much of your work, as I understand, but I'm not a Spring person so I can not speak to the details.
What about spring parentContext?
Check out this article:
http://springtips.blogspot.com/2007/06/using-shared-parent-application-context.html
Terracotta might be a good fit here (disclosure: I am a developer for Terracotta). Terracotta transparently clusters Java objects at the JVM level, and integrates with both Spring and Hibernate. It is free and open source.
As you said, the problem of more than one client web app using an L2 cache is keeping those caches in synch. With Terracotta you can cluster a single Hibernate L2 cache. Each client node works with it's copy of that clustered cache, and Terracotta keeps it in synch. This link explains more.
As for your business objects, you can use Terracotta's Spring integration to cluster your beans - each web app can share clustered bean instances, and Terracotta keeps the clustered state in synch transparently.
Actually, if you want a lightweight solution and don't need transactions or clustering just use Spring support for RMI. It allows to expose Spring beans remotely using simple annotations in the latest versions. See http://static.springframework.org/spring/docs/2.0.x/reference/remoting.html.
You should take a look at the Terracotta Reference Web Application - Examinator. It has most of the components you are looking for - it's got Hibernate, JPA, and Spring with a MySQL backend.
It's been pre-tuned to scale up to 16 nodes, 20k concurrent users.
Check it out here: http://reference.terracotta.org/examinator
Thank you for your answers so far. We're still not quite there, but we have tried a few things now and see things more clearly. Here's a short update:
The solution which appears to be the most viable is EJB. However, this will require some amount of changes in our code, so we're not going to fully implement that solution right now. I'm almost surprised that we haven't been able to find some Spring feature to help us out here.
We have also tried the JNDI route, which ends with the need for stubs for all shared interfaces. This feels like a lot of hassle, considering that everything is on the same server anyway.
Yesterday, we had a small break through with JMX. Although JMX is definately not meant for this kind of use, we have proven that it can be done - with no code changes and a minimal amount of XML (a big Thank You to Spring for MBeanExporter and MBeanProxyFactoryBean). The major drawbacks to this method are performance and the fact that our domain classes must be shared through JBoss' server/lib folder. I.e., we have to remove some dependencies from our WARs and move them to server/lib, else we get ClassCastException when the business layer returns objects from our own domain model. I fully understand why this happens, but it is not ideal for what we're trying to achieve.
I thought it was time for a little update, because what appears to be the best solution will take some time to implement. I'll post our findings here once we've done that job.
Spring does have an integration point that might be of interest to you: EJB 3 injection nterceptor. This enables you to access spring beans from EJBs.
I'm not really sure what you are trying to solve; at the end of the day each jvm will either have replicated instances of the objects, or stubs representing objects existing on another (logical) server.
You could, setup a third 'business logic' server that has a remote api which your two web apps could call. The typical solution is to use EJB, but I think spring has remoting options built into its stack.
The other option is to use some form of shared cache architecture... which will synchronize object changes between the servers, but you still have two sets of instances.
Take a look at JBossCache. It allows you to easily share/replicate maps of data between mulitple JVM instances (same box or different). It is easy to use and has lots of wire level protocol options (TCP, UDP Multicast, etc.).

Categories

Resources