I have several CDI bean controllers, that I would like to reuse within my desktop web applications, and mobile web applications (herein called web-components).
Scenario:
I have one Java EE application (EAR)
I have a web.war component (to refer to the desktop web application)
I have a mobile.war component (to refer to the mobile web application)
I dont want to use responsive design on the main web application because of how it was designed, so I simply need to develop a mobile version, to be accessed at a different subdomain
m.mydomain.com
My intention is to create reusable-component.jar to contain all the CDI controllers, and then include this JAR to the web components.
However, this fails Jboss weld detects the same name for the bean, weld error 00414
However, I have defined some generic request processing lifecycle on this CDI beans e.g.
#OnRequest()
#Named
#RequestScope
public class MyBeanController{
}
The #OnRequest is a lifecycle callback I have defined, which does a lot of things, including permissions to certain resources which are defined externally in a configuration file.
What I have thought about.
Remove the #Named and scope annotations in the reusable-component.jar, and then extend them separately on the different web-components.
Problem, I have several cdi beans, quite a lot because this is a huge applications, and extending each of them in the web-component will be a lot of refactoring.
My question:
How can I manage to reuse this CDI beans, in this web-components?
FYI: I have looked at the alternative/stereotype, specialization scenarios, this will still require me to extends all the beans anyway, and my #OnRequest annotation lifecycle processing does a bean lookup using the #Named or bean name (as specified in cdi), so if I were to use specialization or alternatives, how will this lookup be affected?
What I recommend to most people in this scenario is to define two separate WARs and a common JAR. Include that common JAR within both WARs (as WEB-INF/lib entry). While the JAR is duplicated, the code is not duplicated.
Related
I am new to Spring and would like to convert my existing applications to Spring Boot.
However, I am using a self-written module framework that allows me to add or remove components or additional functions of the application dynamically at runtime. The whole thing can be compared to plugin frameworks like PF4J or the plugin mechanism in Minecraft servers.
The advantage of this is obvious. The application is much more dynamic and certain parts of the program can be updated at runtime without having to restart the whole application.
Under the hood, a new ClassLoader is created for each module when it is loaded. The ClassPath of this ClassLoader contains the JAR file of the module. Afterwards, I load the respective classes with this ClassLoader and execute there an init method, which contains each module.
Now, I would like of course in connection with Spring that both the dependency injection in the modules functions, and that beans or, for example, rest controllers, which are in the modules, register with the module loading and unregister with the module unloading.
Example: I have a staff module. When I register it, the employee endpoint is registered and is functional. When I unload the module, the employee endpoint is removed again.
Now to my problem:
Unfortunately, I don't know how to implement this with Spring, or if something like this is even possible in Spring. Or are there even already other solutions for this?
I also read something about application contexts. Do I have to create a new application context for each module, which I then somehow "closed" when unloading the module?
I hope you can help me, also with code examples.
This post helped me a bit: https://hdpe.me/post/modular-architecture-with-spring-boot/
In short for each module a new ApplicationContext (e.g. AnnotationConfigApplicationContext) is created. If you want to share beans between the modules, you have to publish them to the main application context.
Beans can be registered at runtime by ((GenericApplicationContext) applicationContext).registerBeanDefinition(name, beanDefinition); at the main Application Context.
Another problem is that additional configurations are required, for example for #RestController or similar, in order for them to work. See other questions on StackOverFlow from me.
One of the main advantage of using spring dependency injection is for testing the functionality using same interface with different implementation without making any changes in the code, that is through injecting these different implementations(dependencies) in configuration file.
Lets take an example where we have developed our application with java configuration/annotation based (No .xml files at all).
We have done a code freeze and have deployed the code in server.
Now for a QA team to perform testing they need to inject different implementations for the interface by making changes in configuration file without touching code.
If its a .xml file, devOps team can inject the different implementation by injecting that bean name and can restart the server.
But since we have used the annotations based/java based configuration, How can we achieve this ?
Thanks in advance.
One of the main advantage of using spring dependency injection is for
testing the functionality using same interface with different
implementation
One of main advantages of Spring is indeed the dependency injection facility.
But you will also find very often cases where you have beans with a single implementation :
beans that rely on an interface but there is only one implementation for it.
bean that don't rely on any interface but are straight classes that you want to turn into injectable beans.
We have done a code freeze and have deployed the code in server. Now
for a QA team to perform testing they need to inject different
implementations for the interface by making changes in configuration
file without touching code.
Spring and more generally dependency injection pattern/frameworks are not designed to perform hot swapping or implementation modification of a deployed component without repackaging the component.
At startup, Spring creates its context and loads all required beans for the application in its container.
If you want to change configurations of some beans, the most clean and side effect less way is destroying the spring context/container, repackage the application with the needed changes and restart it.
If its a .xml file, QA team can inject the different implementation by
injecting that bean name and can restart the server.
Ideally, the QA team should test the implementation that you deploy in QA env and that will be used by final users to stay the closest of the real functioning of the application.
Now, if because of some specific constraints, some components to test by the QA should be mocked/stubbed in a some way, just create a different build for that.
Spring Boot Profile and Maven Profile features can help for.
I am new to CDI and I am writing a new CDI portable extension. My CDI extension will listen to events that are fired by the CDI container. I was wondering if there is a way to tell the name of the application that a class belongs to and what are the events that would provide that information.
by application I mean a ear application archive that is deployed on an application server. My goal is to create an extension that looks into applications deployed and for each add an annotation on some of it's classes. Each application classes would have a unique annotation. Example if we have app1 and app2 deployed on an app server. I want to create an extension that would annotate all/some classes contained in app1 with with #x1 and all classes of app2 with #x2 and so on.
To my knowledge, there is no concept of application in CDI. There are only bean archives. You might be able to determine that - e.g. WAR1 will be a different bean archive than WAR2 which in turn will be different than EAR/lib.
BUT, and I cannot stress this enough, the bean archive concept is interpreted slightly differently in Weld and OWB (as CDI implementations) so sticking to this would make in unportable (which probably won't matter since all servers except TomEE use Weld anyway). Truth be told, to even get hold of a bean archive, you might have to rely on Weld API (not just CDI).
But I think it would be wiser to find another way around this - why are you trying to achieve this? What gain is there in annotating beans differently in different archives? Because #Nikos has a good point with class loading. There is a whole new level of mess with EARs and you won't "see" some bean from other archives anyway (as per Java EE umbrella spec).
I want to build an MVC app using Spring (first timer here).
As such I want to embed Jetty as the servlet engine. Jetty however doesn't stricly follow the java beans pattern, so I can't launch some classes from Spring (they use overloaded setters or non setter init methods like addXYZ).
What is the accepted/recommended practice for structuring this project? Obviously all my code fits nicely in the MVC model, but for Jetty:
Do I encapsulate all of Jetty (or any
other non-bean friendly component) in
my own Spring-friendly bean?
Do I try to instantiate as much of it as
possible in spring and just extend
classes that aren't bean con-formant
to make them act like proper beans?
Is there
another option?
Generally speaking, I'm for the 2nd point - i.e. try to use spring utilities like factory-method, init-method, <constructor-arg> and things like that to overcome the fact that something is not entirely spring-friendly. It is rarely the case that it's impossible to configure beans with spring. And for the cases when it is impossible, create wrappers
You can also instantiate the 3rd party beans programatically:
via a FactoryBean
via JavaConfig
I'm new to EJB 3 and pretty confused with some doubts which Google didn't provide with a satisfactory answer.
I'm trying to create a framework with some base classes and some utility methods which my other applications can use. All applications are to be deployed on the same server.
When I'm trying to create a new EJB 3.0 project in eclipse, it asks if I want to create a client jar also. What purpose does this client jar serve? My ejbmodule is added as a part of the EAR file. So do I really need this client jar?
Do I need to create both local and remote interfaces? Or just remote interfaces will do?
I decided to keep all the interfaces in a project called projCommon and the bean definitions in projApps. The remote interfaces which the bean classes implement are in projCommon. So projApps is dependent on projCommon.
I plan to use a delegate method defined in projCommon to invoke the bean classes. That will mean that projCommon is also dependent on projApps, rt? And lead to a circular dependency.
How exactly are EJB's directly injected?
Would be really helpful if you can kindly provide an explanation to my doubts.
When I'm trying to create a new EJB
3.0 project in eclipse, it asks if I want to create a client jar also. What
purpose does this client jar serve?
An EJB client JAR file is an optional JAR file that can contain all the class files that a client program needs to use the client view of the enterprise beans that are contained in the EJB JAR file. If you decide not to create a client JAR file for an EJB module, all of the client interface classes will be in the EJB JAR file
My ejbmodule is added as a part of the
EAR file. So do I really need this
client jar?
You do not really need the EJB Client it just provides an easier packaging to use the EJBs from a client.
Do I need to create both local and
remote interfaces? Or just remote
interfaces will do?
If all your EJBs are in the same EAR then you can use local interfaces, if not you need remote interfaces. Local interfaces are more efficient, the calls are done be reference.
Some Containers (i.e. WebSphere) will optimize this at runtime for you and automatically call local interfaces if it is possible.
I decided to keep all the interfaces
in a project called projCommon and the
bean definitions in projApps. The
remote interfaces which the bean
classes implement are in projCommon.
So projApps is dependent on
projCommon.
I would keep my projects organized by functional areas. Make local calls within the functional areas and remote ones outside of the functional areas, This allows you to later split the functionality to be deployed on different servers to scale it. It also keeps the code more modular. This also avoids any circular dependencies.
How exactly are EJB's directly
injected?
The how it works does not matter, That is going to be done by the container. The whole point of J2EE is to abstract out the how.
As per http://www.developer.com/print.php/3650661:
EJB 3 containers provide the facilities to inject various types of resources into stateless session beans. Typically, in order to perform user tasks or process requests from client applications, the business methods in the session bean require one or more types of resources. These resources can be other session beans, data sources, or message queues.
The resources that the stateless session bean is trying to use can be injected using annotations or deployment descriptors. Resources can be acquired by annotation of instance variables or annotation of the setter methods.
See here for more details. Hope this help.