Spring 3.1 Environment Abstraction and EJB integration - spring

I'm trying to use the new environment abstraction in our Java EE/EJB application. We're already using SpringBeanAutowiringInterceptor to inject Spring Beans into EJBs by using the standard beanRefContext.xml to bootstrap the shared application context for the Java EE app.
Now I've written a concrete Environment class (derived from Spring 3.1 AbstractEnvironment) which uses some kind of environment "auto" detection to select the correct active profile for the machine on which the app is running on. With this feature our app can be delivered with all properties for all environements (inside the ear) and auto select the correct property set.
The problem is now that org.springframework.beans.factory.access.SingletonBeanFactoryLocator.createDefinition(String, String) builds a bean factory group around the beans/context in beanRefContext.xml using the StandardEnvironment class, and I see no simple way to configure the environment implementation to use here without rewriting(overwriting) some part of SingletonBeanFactoryLocator.
Is there a simple solution for this, or is s.th. planned in the direction for supporting to specify the Environment implementation with the EJB/Java EE integration?

Related

Is it possible to access the spring context outside of a spring-boot application?

I am trying to create a standalone database application which can offer CRUD operations to other applications/modules...
I am aware of the need to create the entities and services used by the application in another artifact since you cannot depend on a spring-boot application alone.
But, can one get the runtime spring-configuration of a spring-boot application? So one can access a service that is deployed on my application?
For best through-put I am looking for a way to use services on a running spring-boot database application on the same JVM in order to minimise overhead...
RMI
What you want is technically it is possible using basic Java RMI (remote method invocation), you just register the bean as the implementation instance and share the interface between the two JVMs, either on localhost or even on different machines.
Spring even gives some additional support for this using RmiProxyFactoryBean, see Spring Remoting RMI article.
From above article, you can export it, using:
#Bean
RmiServiceExporter exporter(CabBookingService implementation) {
Class<CabBookingService> serviceInterface = CabBookingService.class;
RmiServiceExporter exporter = new RmiServiceExporter();
exporter.setServiceInterface(serviceInterface);
exporter.setService(implementation);
exporter.setServiceName(serviceInterface.getSimpleName());
exporter.setRegistryPort(1099);
return exporter;
}
and import it, using:
#Bean
RmiProxyFactoryBean service() {
RmiProxyFactoryBean rmiProxyFactory = new RmiProxyFactoryBean();
rmiProxyFactory.setServiceUrl("rmi://localhost:1099/CabBookingService");
rmiProxyFactory.setServiceInterface(CabBookingService.class);
return rmiProxyFactory;
}
Then you can use it in your application context based on your interface.
However I would not suggest to share beans like this because it has the same problem RMI has.
Shared library
Another way to do what you want is to create a shared library that can be included in other projects.
If all the project, which want to use it are Spring Boot application you can create a Spring Boot starter, see Spring documentation.
This way, other applications just have to add the dependency and they already has access to the beans in their application context, as well as the shared domain objects.
If other application use just regular Spring, they can just #Import your main configuration class.
If other apps are using Java, but not Spring, you can still use Spring inside, just provide a factory, which creates an internal Spring context.
REST service
If other applications are not written in Java, your best bet is to expose a REST interface for them to use the database applications.

Using SpringBoot as an application loader

I have a spring-boot app that acts as a small framework for other apps. It provides a couple of JMS queues and a DAO layer to retrieve and store data from a common set of data stores. The problem is that the original developer of this framework app is scanning all the package "com.mycompany" (rather than com.mycompany.framework) so that it can load the beans of the specific app that may be declared under com.mycompany.myapp1 or com.mycompany.myapp2 an which JARs are bundled together with the JARs of the framework.
We only load a single app in the JVM (app1 or app2), but these apps may share other libraries and sometimes we end up with beans in the context that we don't need. (these may be needed in app1 but not in app2)
So, what would be your advice ?
My problem is similar to what was described here:
https://github.com/spring-projects/spring-boot/issues/3300
I am debating if each app should be aware of the framework and load it. Or if the framework should instantiate a class loader and create a new Spring context loading the app specific code as suggested in the link above.
Perhaps you should consider leveraging some of Spring Boot's Auto Configuration capabilities such as #ConditionalOnProperty or #ConditionalOnClass in your framework. That way, you can only actually enable certain beans if and when the application using your framework takes some specific action (e.g. has a given jar on the classpath, or sets a configuration value). For reference check out: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-developing-auto-configuration

Asynchronous task execution using Spring in container managed environment

I want to run few tasks asynchronously in a web application. My question is which Spring implementation of task executors i should use in a Container managed environment.
I refereed to this chapter in Spring documentation and found few options.
One option I considered is WorkManagerTaskExecutor. This is very simple and works seamlessly with the IBM Websepher server which I'm currently using but this is very specific to IBM Websphere and Oracle Weblogic servers. I don't want to tie my code specifically to one particular implementation as in some test and local regions we are using Jetty container & this implementation creates problems to run the code in Jetty.
Other options like SimpleThreadPoolTaskExecutor does not seem to be best fit to leverage thread pooling in container managed environment and I don't want to create new thread myself.
Could you pleas suggest how do I go about this. Any pointers to a sample implementation will be great help.
As usual, it depends. If you rely on the container's thread management and want to be able to set thread pools on its admin interface or if you're application is not the only app inside the container or you use specific features like setting thread pool priorities for EJB or JMS you should add support for the WorkManagerTaskExecutor and make it configurable. If not, you can use whatever you want cause in the end threads are just threads. Since Spring is an IOC container you can do it. To use the same app everywhere I wouldn't suggest to change the XML config per app version. Rather
use profiles with configuration to set the executor type and inside your java config return the proper bean type. If you use Jetty you should have a configuration for the thread pool sizes to to be able to tune it.
use spring boot like auto configuration which usually rely on available classes on classpath (#ConditionalOnClass). If your weblogic or websphere specific classes are available or any other container specific thing like env variables you can create the WorkManagerTaskExecutor
With both of these you can deploy the same war everywhere.

"Open Live Beans Graph" is disabled

I have a Spring MVC project inside of Spring Tools Suite that uses Java based Spring configuration and Gradle.
- I've added the Spring Project Nature.
- I'm not using #ComponentScan, I define all beans explicitly.
- I have "Auto detection for annotated Java Spring configuration files" turned on.
Why is "Open Live Beans Graph" disabled (greyed out) in my Project/Spring Tools menu?
Thanks!
The live beans graph is showing the beans that are being created in the running application, so you need to run the app (in your case I guess you run that in tc Server), and open the live beans graph view for that application. You can do that from the tc Server editor, there is a section for live bean graphs being available (and you can enable the feature in general).
If you do not run the app in tc Server, you have to set a property in order to enable this feature in your running application and connect to that application from the live beans graph view manually.
Hope that helps!
Spring MVC may not be enough to get it to work.
https://docs.spring.io/sts/nan/v310/NewAndNoteworthy.html says:
To allow proper communication, servers must be configured to enable
JMX and must also be given the VM argument
'-Dspring.liveBeansView.mbeanDomain' in order for the Spring Framework
to produce the data required to build up the graph.
I think the easiest is to get it to run in Spring Boot.
https://codecentric.github.io/spring-boot-admin/1.4.3/#jmx-bean-management

Is it possible to set up Jetty with CDI for websockets?

I have managed to get weld CDI to work with jetty embedded for both servlets and rest. My question is: Is it possible to get CDI to work with WebSockets (JSR-356)?
CDI with javax.websocket is not well defined in the official JSR-356 spec, and wiring it up has proven sufficiently odd that each implementation is doing it differently, with different levels of support.
(This is likely because the JSR-356 spec was written to be intentionally unconnected to Java EE and Servlet in general, allowing it to exist in non Java EE environments)
There are a few open issues with it at the Jetty side.
423647 - New Extensions should be created via ServletContextHandler.createInstance(Class)
423645 - New ClientEndpointConfig.Configurators should be created via ServletContextHandler.createInstance(Class)
423367 - New ServerApplicationConfig objects should be created via ServletContextHandler.createInstance(Class)
423365 - New ServerEndpointConfig.Configurators should be created via ServletContextHandler.createInstance(Class)
423364 - New Encoders should be created via ServletContextHandler.createInstance(Class)
423363 - New Decoders should be created via ServletContextHandler.createInstance(Class)
423336 - New Endpoints should be created via ServletContextHandler.createInstance(Class)
I'm one of the maintainers of the websocket impl at Jetty, and would love to have someone help test the CDI integration (none of the Jetty developers themselves use CDI so its hard to get good, real-world, test cases to work against)

Resources