When calling remote EJB3 (Glassfish) from another EJB module, it is usual to have interfaces available, they are included as JAR file so that when you do JNDI lookup everything works as expected.
I have a situation where EJB3 JNDI name is determined at runtime, and my attempts to access the EJBs retrieved from JNDI in usual way fail, container complains ClassNotFound for remote interface classes. This is odd to me, since all the interface classes extend a parent interface for which I DO have a dependency in my calling EJB module, i.e.:
IParent ejbRef = (IParent) JndiLocator.getObject("jndinameRemote");
Is this possible with EJB3, without the need to have an exact remote EJB interface bytecode available in my JAR?
Bozo
Even though i am exactly not sure what the above setup is , I had a similar need of trying to invoke EJB when the client jars are not known during the compile time, infact in addition there is also no way for me to know what Application service is the EJB deployed at.
I had managed to do this by writing my Customized Class Loader , the catch here is that the Class which in turn tries to invoke the EJB must be itself loaded using the Customized class loader along with all the necessary jars i.e client jar with interfaces and models and the application server specific client jar.
I passed all the context properties as an input to my Invoker class to initialize context factory and invoke the bean.
These are high level steps to achieve this
Create Class EJBInvoker with method invokeEJB, you can pass it couple of Maps with properties for preparing context and Ejb interface , method , parameters classes , values and output class.
Use reflection to create instance of InitialContextFactory as well as Bean object , parameters and method invokation.
Add the above class to separate jar file and invoke the method with properties required from external project using a customized class loader.
Related
I have multi module maven project,which has one common module which is being used by other modules. In common module I have few beans(Beans are having singleton scope) that are used by other modules application context. Now the problem is having after using those beans in one module(m1) which was not previously using these beans. Importing the common.xml(Beans are defined here) in Application context of module(m1) generates lot of issue(Cannot find the beans). So I decided to directly use those beans in application context of module(m1). If I keep the scope of beans to singelton , I get java.lang.UnsatisfiedLinkError: no jzmq in java.library.path. This issue is solved by using prototype as scope.
Any idea about this issue.
1 Using native methods make your Java application code platform dependent.
2 The System.loadLibrary method is equivalent as executing the Runtime.getRuntime().loadLibrary method.
3 The System.loadLibrary method shall be used in a static initializer block, in order to be loaded only once, when the JVM loads the class for the first time.
I have a Spring Boot project for which one of the developers has written Integration tests against an in-memory DB. Here is some background before I put my question :
We have following Maven modules :
1) web-persistence : which store all entities and interfaces and corresponding implementations. All these classes are in package com.mycompany.persistence.
2) web-services : which stores all our rest controllers and spring security related classes. These are all in package com.mycompany.services
3) web-services module has maven module dependency on web-persistence module.
4) In web-services module we have defined a service UserContextServiceImpl which is implementation of interface IUserContextService. This service basically encapsulates Spring's SecurityContextHolder functionality by exposing only those parts of a current user related information which is needed through its methods so that everywhere we don't have to use SecurityContextHolder. The implementation class is annotated with #Service("userContextService").
5) Interface IUserContextService is in persistence module. There is another class AppDependecyHeper in persistence module which implements ApplicationContextAware and returns UserContextService's concrete instance by calling appContext.getBean('userContextService') where appContext is holding ApplicationContext when application is initialized.
6) Now we don't want to expose Spring Security classes in persistence module(for reasons which are out of context here) and hence above arrangement of getting current user information through a service by calling getBean() method of applicationContext in persistence layer class AppDependencyHelper. This information is then used to update audit fields createdBy and modifiedBy using an EntityListener.
7) Actual application uses only single ApplicationContext where both persistence layer classes and web controllers are loaded in one single spring context.
8) Everything works fine when application runs. However when our integration test Runs the call appContext.getBean('userContextService') fails and throws NosuchBeanDefinitionException as it is unable to find the bean with name 'userContextService'
9) Now finally the code of our integration Test (only giving relevant details) which is located in com.mycompany.persistence.embeddeddb package:
#Runwith(SpringJUnit4ClassRunner.class)
#ConfigurationContext
class MyEntityTest{
#Configuration
#ComponentScan("com.mycompany.persistence")
public static class Config{
.....
}
.....//code which eventually gives call to
AppDependencyHelper's method which in turn tries to retrieve userContextService Bean.
}
Now the questions :
1) Why it fails to retrieve the bean? I have tried addingcom.mycompany.services like below
#ComponentScan({"com.mycompany.persistence","com.mycompany.services"})
but to no avail.
2) What I am able to understand by reading whatever I got is that #ContextConfiguration needs to be provided with either XML files or Annotated classes or WebApplicationInitializers(in my case as we are having only single ApplicationContext) to create an ApplicationContext from #Configuration classes. However I cannot do that as maven starts complaining about circular dependency which is rightly so as my #Service annotated class UserContextServiceImpl is in web-services module which is dependent on web-persistence module already where the test case class is written.
3) The only solution I can think of is moving all integrations test classes to web-services module so that I can tell #ConfigurationContext all the classes from which it should create an ApplicationContext.Am I right?
Last point : The ApplicationContext class is of type GenericApplciationContext when I run tests. When I run application its obviously AnnotatedEmbeddedWebApplicationContext
please let me know if there is any solution to this problem?
From what I'm guessing you are trying to use a component from your web-service module in your integration tests. If that's the case, than yes, you should move your integration test cases to your web-service module - as you've already suggested in your question.
EDIT: You should really rethink your design, because you have a circular dependency problem here: Your web-service module depends on web-persistence, but the implementation of your IUserContextService in web-persistence is found in web-service.
You should probably move your IUserContextService (and all your integration tests) to your web-service package.
I am using jersey-guice to set up all my Jersey 1 resources using a bunch of Guice (Servlet)Modules.
I have written a custom ViewProcessor (CustomViewProcessor) that relies on a configuration object, that I want to be injected into it using Guice. This CustomViewProcessor should be picked up and used by Jersey every time it needs one.
How do I tell Jersey to fetch a Guice-created CustomViewProcessor instance whenever it needs a ViewProcessor? I want to set all this up within my Guice Modules' configure methods.
I found out that this is rather easy: Just create that CustomViewProcessor class and annotate it with #Provider. By binding it with Guice (and having jersey-guice installed), your CustomViewProcessor will be instantiated and used in the right places.
The CustomViewProcessor class can use all the #Injected fields that you wish, like configuration objects.
This is more of a design question. My project's structure is like this - I have a dozen frontend classes, some service layer classes and a single backend class which contacts an external system. I use spring to initialize and inject the backend class instance into the service class beans, and in turn the service class beans into the frontend class beans (as appropriate).
The frontend classes are (logically) divided into modules. The service layer and backend are common.
Now, my requirement is that the backend class methods need to send out a different value for a field to the external system, based on the module of the frontend class making the call.
To make it more simple, consider a (somewhat crude) usecase where the backend class connects to a DB for each method call. DB calls originated by module A's frontend classes, must always connect with the username "moduleA". Similarly all calls from module B must result in connections using username "moduleB". Note, the behavior itself is common regardless of caller -- just the username must be different.
Most trivial way is to let each frontend class bean have its own copy of service layer class bean, which in turn has its own copy of backend class bean. For eg, module A's frontend beans will refer to the moduleA service bean, which will refer to moduleA backend bean. I can inject module A's username into module A's backend bean in this case. Similarly there will be a set of bean definitions (frontend + service + backend) for moduleB.
But I don't want to create so many bean definitions. The other trivial way is to pass the value from frontend all the way to backend in all methods. But this is a widespread change. Is there a simpler way using Spring?
You should try passing the values using thread local (if your modules are running inside the same JVM)
Be careful to clean the thread in a servlet filter via a finally method.
I'm using JBoss 7.1.1 with CDI.
I've got a Stateless bean named ServiceAccount in JNDI. This is the real service implementation.
I've got another Statelss bean named ServiceAccountMock which is a Mock service.
The both herited from the same interface and are packaged in a service.ear.
What I want to do is to declare the mock service as alternative in bean.xml, redeploy my services ear, and then all the client see the mock version (without changing anything on client side).
When I deploy my service.ear, JBoss says :
java.lang.IllegalArgumentException: JBAS011046: A component named 'ServiceAccount' is already defined in this module
This is true, both services are declared the same way (#Stateless(name="ServiceAccount")).
If I change the name of the mock version, I have to change on client side which EJB is used (and I don't want to do that).
Does anyone know how to do that ?
I don't think you will be able to deploy 2 beans with the same name in the same application.
If the clients of the bean are only local, you should use CDI type injection selection.
Remove the name of the beans or put different name if you realy need a name (The mock will have a different name that the real implementation).
Keep the #Alternative annotation on the mock.
At the injection point, use the interface as the type of variable (and probably using the #Inject annotation instead of the #EJB one may help).
The EJB specification and CDI aren't yet completly aligned. EJB has some element like the name that need to be unique over the application and is not taken into account in the CDI alternative functionaltity.
So I don't think you will be able to mix EJB name injection selection and CDI alternative injection selection.
First you need to annotate ServiceAccountMock with #Alternative, to tell the container not to use it if not instructed to.
#Stateless(name="ServiceAccount")
#Alternative
public class ServiceAccountMock{
....
}
Then in beans.xml you need to tell the A/S to pick the mock implementation:
...
<alternatives>
<class>xx.yy.ServiceAccountMock</class>
</alternatives>
...