Spring interceptors using #configuration - java

I'v mostly used XML based configuration for applicationContexts. I have a requirement where I need to use #configuration to create my beans using #Bean now.
Brief description of why ?
weblogic deploys a spring web-app "A". A makes calls to B(not spring,not web app-no WEB_INF). B just contains common service calls to external servers. Hence B.jar is bundled into A and A is then deployed on web-logic.
Now i need to use spring beans in B.)
So the options available at this point:
Bundle applicationContext.xml and all the property files into B.jar. (keep in mind it is a very complex build process with 20 property files and 100s of beans. So I also need to register propertymanager bean etc..). Then initialize appcontext in a static initializer block and look for appcontext within B.jar.
Use #configuration to register an Appconfig.class instead of an XML. (no changes to build process here).
With this option i need to use a clientInterceptor. Could you provide me with the #Bean definition of this.
How do I configure clientInterceptor in #appconfig.class.
*please let me know if there any other options.
Spring-ws-core - 2.1.4.release
spring-core-3.2.4
expression,context,beans - 3.0.5
spring-oxm-1.0.3
weblogic - 12c
jdk - 1.7
This is my first post here. Any suggestions would be welcome and appreciated. Apologize for any forum faux paus.

Related

Adding a conditional external PropertySource in a spring boot application

I'm currently using an EnvironmentPostProcessor to add my external PropertySource, the code looks like this :
public class ExternalPropertySourceEnvironmentPostProcessor implements EnvironmentPostProcessor
{
private static final String EXTERNAL_PROPERTY_SOURCE_NAME = "ExternalPropertySource";
#Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application)
{
if (environment.acceptsProfiles(Profiles.EXTERNAL_PROPERTY_SOURCE_ENABLED_PROFILE)) {
environment.getPropertySources()
.addLast(new ExternalPropertySource(EXTERNAL_PROPERTY_SOURCE_NAME, new ExternalSource()));
}
}
}
A spring.factories is also used to register this EnvironmentPostProcessor.
This code actually works if the profile is set in the vm environment variables, but if it is added in src/main/resources/application.yml, the profile doesn't seem to be injected yet in the environment and is not returned by the environment.getActiveProfiles(). I've tried using the interface Ordered with the lowest precedence, but it doesn't help.
To add a bit of context around what I'm trying to achieve, this class is in a small library that adds an external property source like a database. Then we can use it in some other spring boot applications. Something like Spring Cloud Config does.
I'd like a clean way to enable or disable this property source depending on the environment where the code runs. I don't mind using something else then profiles or even another way to inject the property source, I just want something clean that doesn't depend on several factors to work.
The main problem in my code right now is that I'm using spring boot's property sources to make my own property source configurable.
UPDATE : I used a Spring Cloud app to debug this, and was confusing the bootstrap context with the normal spring boot context. See my answer below.
Further investigation made me figure out the problem appeared only with a Spring Cloud application.
In fact the breakpoint I had in this code was triggered twice, once after the bootstrap context initialization and once after the spring boot context initialization. I was only debugging the profiles in the first occurence. At that point, only the bootstrap.yml properties are loaded and not the ones from the application.yml file. The second occurence obviously had the profiles from my application.yml file.
My code worked as expected with a vanilla Spring Boot application. As the documentation states :
The Environment has already been prepared with all the usual property
sources that Spring Boot loads by default.
I was confused by the behaviour of my app which seemed to be different from that statement, but it was Spring Cloud's bootstrap that was messing with my debugging.
Since I need a PropertySource that has the highest precedence, I need to add it in the post bootstrap initialization for Spring Cloud apps. I used an init flag on my EnvironmentPostProcessor so it doesn't get executed twice and used the bootstrap.yml on Spring Cloud apps to set the profile.
TL;DR :
With Spring Cloud, an EnvironmentPostProcessor gets called twice: once after the bootstrap init and once after the normal Spring Boot context init. If you need injected properties and are targeting the Spring Cloud's post bootstrap initialization, use the bootstrap.yml instead of application.yml.

Convert traditional projects to spring boot, without changing applicationContext.xml, dispatcher-servlet.xml & tomcat's context.xml

The background & requirements are:
there are a lot of old projects which have an applicationContext.xml and one or more dispatcher[-XXX]-servlet.xml. We hope those projects can still works while using spring boot(we developed a deployment tools to deploy spring boot applications, but the old projects are still deployed manually). But, #SpringBootApplication can't build the contexts as they were. And rewriting them into codes one by one costs too much, I think.
In those project, we use an extended RequestMappingHandlerMapping, so we can't use the native MVC.
the context.xml of tomcat, which contains jndi definitions, is maintained by OPs. We have to load it just like tomcat does.
i can't find where to set welcome file, which were set in web.xml
I currently using:
#Configuration
#ImportResource({"classpath:/applicationContext.xml", "classpath:/dispatcher-servlet.xml"})
Those simple projects without using jndi can startup.
But as my understanding, in this case, the applicationContext and dispatcher-servlet are in the same level(dispatcher-servlet should the child of applicationContext, isn't it?). So, i can't even ensure this one works properly.
We did a similar thing about a year ago and your setup was more or less the same as ours and importing those XML files did the trick; the only thing we had to do was to ensure our application class was in a different package hierarchy in order to avoid conflicting/duplicate bean definitions due to its inherent #ComponentScan.
And having dispatcher servlet and application context in the same context won't cause any issues - yes, dispatcher servlet's context is usually defined as a separate context and is a child of the more broad applicationContext but what most people fail to grasp is that that separation only matters if your application wants to have more than one dispatcher servlet, which is rarely the case any more, if it ever was.
In case of multiple dispatcher servlets it was a must to enable them to have different WebMVC configurations, and applicationContext was there to allow you to share common beans and configuration between your servlet contexts so that you don't have to do the same work twice.

How to update configuration of SpringBoot application at runtime without reloading whole ApplicationContext

I am trying to figure out how can I dynamically update/reload externalized configuration in a Spring Boot application without restarting the whole application.
Most of the advice involves reloading ApplicationContext after changing the externalized configuration, but that is equivalent to restarting the entire application, so this is not really all that useful.
Reading through SpringBoot reference documentation, I found a chapter 23.7 Typesafe Configuration Properties.
If I understand it correctly, this allows to define simple POJO classes that will hold your application (externalized) configuration values as attributes.
In theory at least, this scheme could be used to bind beans only once to the required configuration POJO and upon configuration change just update the values in the POJO. Components could easily pick up the changes next time they access getters on the POJO...
However, I have yet not managed to figure out how to enable this type of behavior. Is there some glaringly obvious way to dynamically update components annotated with #ConfigurationProperties when relevant configuration has changed?
It sounds like you're looking for #RefreshScope which is provided by Spring Cloud. From the Spring Cloud documentation:
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.

Spring how to do the official Spring REST tutorial without using #ComponentScan?

Here's the tutorial refering to the part where it quotes
The #ComponentScan annotation tells Spring to search recursively through the hello package and its children for classes marked directly or indirectly with Spring’s #Component annotation.
http://spring.io/guides/gs/rest-service/#_make_the_application_executable
I don't want to make my service an application, instead, I want to deploy it in JBoss as a WAR.
How do you make Spring find your Controller without the #ComponentScan
Lets start with the most strait forward question.
1) How do you make Spring find your Controller without the #ComponentScan
You can instantiate the Controller beans by explicite name them in the spring configuration xml
<bean id="myBean" class="com.example.MyBean">...</bean>
2) I don't want to make my service an application, instead, I want to deploy it in JBoss as a WAR.
A normal Spring Web Application is a normal WAR file that can been deployed like every other (Servlet based) war file in ever Servlet container, even to JBoss.
I think that you get confused by the term application, but I think that Spring, JBoss and you mean differentthings by an application
The Point is: that Component Scan is a way to find and instantiate Spring Beans (Java Objects that are maintained in a Spring Container), but this has no meaningful connection to "I don't want to make my service an application, instead, I want to deploy it in JBoss as a WAR."

Apply around advice to existing EJB

We have a third party application deployed on JBoss and Weblogic. We need to log access to EJBs in this application for audit purposes. Is it possible to apply a transparent service that will log all calls to these EJBs to a file or database ?
The only option that I can think of is to use Spring as a business delegate and modify clients to use the Spring bean. Unfortunately, we do not have an option of modifying client code and this has to be done on the server in a way that our code gets executed before and after EJBs are invoked by clients.
I searched for a solution for this and have found nothing that could point me the right direction.
Thank you for the help.
Edit:
After further research, it appears that JBoss does support custom EJB interceptors. Configuration for this is possible using standardjboss.xml for EJB 2.x and ejb3-interceptors-aop.xml for EJB 3.x
As it turns out, there is not much available by way of samples on how to create such interceptors for use with EJB 2.x - which is what I need. It does not appear too difficult and I will try this to see if it works.
You should be able to just use straight forward EJB 3 interceptors. Look for DefaultInterceptor in http://docs.jboss.org/ejb3/docs/tutorial/1.0.7/html/EJB3_Interceptors.html to see how to apply an interceptor to all ejbs in your deployment. This is supported by the EJB 3 spec.
For EJB 2.x in JBoss, take a look at standard-jboss.xml. There you can either modify the full default containers for the different ejb types. You can also create a new container configuration in standard-jboss.xml and add your interceptors there and associate your EJBs with the new configuration by including a jboss.xml in your ejb.jar META-INF/ folder. Or, if I remember correctly, you can both define the new container configuration and the association in META-INF/jboss.xml. Some information here: http://docs.jboss.org/jbossas/docs/Server_Configuration_Guide/4/html/EJBDeployer_MBean-Container_configuration_information.html

Categories

Resources