Inject multiple remote EJBs in bean - java

In Java EE, if I have an interface:
#Remote
public interface MetaService {
ServiceData get();
}
And I have, in an ear 2 implementations:
#Stateless
public class Service1MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
#Stateless
public class Service2MetaService implements Calculator {
#Override
public ServiceData get() {...}
}
I can create a bean, where:
#Stateless
public class View {
#Inject
private Instance<MetaService> metaServices;
...
}
And in View, the field metaServices will have the 2 implementations of MetaService.
I'd like similar functionality with remote beans.
So let's say, I have the above interface and implementations, but the packaging is different.
In base.jar I have the MetaService interface. This is packaged will all the subsequent applications mentioned below.
In a.ear I have the Service1MetaService implementation, while in b.ear I have the Service2MetaService implementation and in c.war I have the View class, which would like to use these implementations.
But as you would expect, the injected Instance is empty (not null tho). Is there a way to find the remote bean references in my injected Instance instance, even though these implementations are in separate applications?
One important thing is that in the View class I don't know and don't care about the number of these implementations, nor the names of the applications they are deployed in. So there is no way for me to use specific JNDI strings to get these references.
P.S.: Should I try and use technologies like JMS instead? So that I call the method add on a JMS proxy, which sends out the requests and waits for answers from all the applications that implement said interface?
P.S.: To clarify, the reason I need this is actually so that I can get data of running services on my application server(s). I updated the example interface and implementations, so that it's more clear. Also, it would be nice, if I could get these metadata synchronously, so JMS is not neccessarily prefered, however I can probably make it work.

I managed to convince myself to move away from remote EJBs. Well, it was also thanks to #chrylis-onstrike- as well, however, I'll opt for using JMS for this purpose.
The reason is that I can broadcast a request for the different services I need data from on-demand, enabling me to check for new services going online, or services failing.
Thanks to everyone who spent time trying to help me out.

Related

Lookup for EJB subclass by superclass EJB name

I have a parent and child EJB
#Stateless
#Local(MyCoreLocal.class)
#Remote(MyCore.class)
public class MyCoreEjb implements MyCoreLocal, MyCore {
...
}
#Stateless
#Local(MyCustomizationLocal.class)
#Remote(MyCustomization.class)
public class MyCustomizationEjb extends MyCoreEjb implements MyCustomizationLocal, MyCustomization{
...
}
for architecural reasons at my company, I can't change MyCore project. But both it's all packed together in the same jar and deployed to JBOSS 4.2.3.
The problem is, I have to use MyCustomizationEjb whenever someone calls for MyCoreEjb. How can I override the JNDI entry for MyCoreEjb to point to MyCustomizationEjb in order to redirect all calls for MyCoreEjb transparently to MyCustomizationEjb?
ps: I have full control over ejb-jar.xml of the project, but can't change annotations.
I figured out a way how i could overpass the problem. In reality i didn't need to redirect all call for MyCustomizationEjb. I needed it just for a particular method (at this time).
So my solution was to make a Method Interceptor on the specific method I wanted and just "redirect" the execution to MyCustomizationEjb like this:
public class SpecificMethodInterceptor{
#EJB
MyCustomization myCustomization;
#AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Object result = myCustomization.specificMethod((Param1Type)ctx.getParameters()[0], (Param2Type) ctx.getParameters()[1]);
return result;
}
This way I could now call the extended specificMethod transparently.
I know this is not the most maintainable or scalable solution (since I'll need one interceptor for each method I want to override), but giving this particular project limitations I believe it was the best choice.
Note: There is no problem for not continue the execution (with ctx.proceed()) because this Interceptor is the last one called before the execution reaches the EJB. The only way it could go wrong is if someone make a method interceptor at the EJB, which would be skipped in the execution. But it's not a problem in this particular project.

EJB Priority over same binding name

Say I have an EJB with the following configuration:
package com.main.notsimulated
#Singleton
#EJB(name = "java:/sample/MainOne", beanInterface = MainOne.class)
public class MainOne {}
This ejb needs to be present for some other deployables to work. However, using this MainOne modue is not very feasable for me in a testing env. Instead, I would rather inject my own custom version at runtime.
package com.main.simulated
#Singleton
#EJB(name = "java:/sample/MainOne", beanInterface = MainOne.class)
public class MainOne {}
(Note, these are two different jar files)
Hence, my idea here is, let's try to replace the currently deployed with a custom version on the fly. The reason I want to do this is because I do not want to change the nonsimulated version at all, nor effect the consumers of the ejb in any way. i.e All that the consumer currently does is look for that particular jndi name, and performs an indejection and a casting to a particular interface.
I have looked at this post in hopes of figuring out if my MainOne Class from com.main.simulated can evict the currently instantiated MainOne class. However, the the selected answer states it is not programatically possible to start or stop an ejb. I have also looked at this post, but this is more of a practical guide as to how we can inject these beans inour calls.
Hence, my question is, can my latter implementation (com.main.simulated) somehow "replace" the other bean, and ensure the com.main.notsimulated version is never executed?
Deploying two classes, with the same binding is obviously not possible. When trying to do so, one will get a binding exception. However, contrary to my original research, programatically binding a bean is entirely possible. Hence, the solution as to how one can "hijack" an old binding, and replace it with the new is as follows: (Note, replace the class names with what you need)
package com.main.simulated
#Startup
#Singleton
public class MainOne {
#PostConstruct
private void rebindClass() throws NamingException {
final Context context = new InitialContext();
context.rebind("java:/sample/MainOne", this);
}
// other methods that will be called
}
Three important things about this class are: Removal of the #EJB annotation, the #Startup annotation and the rebind of context. The #Startup ensures the #PostConstruct method gets called when our container loads our class. When this happens, the method rebinds a class for a value. Hence, this is the hijack location.
Hope this helps someone.

Using hystrix-javanica annotations on interfaces

I am integrating Hystrix into SilverWare microservices platform and I want to use hystrix-javanica annotations. These annotations are meant to be applied on the actual implementation of the methods that need to be executed using Hystrix. The problem is that I need to implement a generic solution where you only have a service interface. It has to be done this way in order to let developers use annotated references to other microservices (when they implement their own service) without any need to deal with the implementation of those services.
I came up with a solution where you annotate your microservice reference with something like this:
#Inject
#MicroserviceReference
#HystrixConfiguration(MyServiceHystrix.class)
private MyService myService;
And then you implement (or extend) the service interface and put Hystrix annotations on its methods:
public interface HystrixedMyService extends MyService {
#HystrixCommand
doSomething();
}
When there is #HystrixConfiguration annotation on a field in your microservice referencing another service, SilverWare will scan the class given as a parameter of this annotation and prepare a Hystrix command for every method of the service. The command will also receive a callable with an actual method invocation which will be executed in its run() method.
My question is: Is it possible to reuse some (internal) parts of hystrix-javanica so I do not need to scan all the annotations and create those Hystrix commands myself? I can see that most of the classes are designed to be used only with AOP.

Is it best to use type or properties to choose between OSGi Declarative Services?

I'm currently converting a piece of code from plain Java code to OSGi Declarative Services.
Original plain Java code
new AggregateServiceImpl(
new ChildServiceImpl1(),
new ChildServiceImpl2(),
new ChildServiceImpl3()
);
The classes are declared as so:
class AggregateServiceImpl implements Service
class ChildServiceImpl1 implements Service
class ChildServiceImpl2 implements Service
class ChildServiceImpl3 implements Service
So all classes implement Service, but the Aggregate implementation is capable of deferring to child Services when called upon.
AggregateServiceImpl itself does not know of the other implementations' existence. Its constructor is originally declared as:
public class AggregateServiceImpl(Service... children)
Clarification: the interface name 'Service' is intended generically and is not meant to represent an OSGi DS or Service concept.
Converting to OSGi
First I move each implementation into its own bundle. Then I declare my components (service implementations). I happen to be using bnd, so I use service annotations. For example:
#Component
class ChildServiceImpl1 implements Service
In the client class, we can look up the Service using the low level OSGi API or use DS in that bundle to create the object for us.
Problem
What's the best way of looking up a 'Service'? I want the AggregateServiceImpl but I might receive one of the ChildServiceImpls.
Is it best to use a separate service type or add a property to one of the components (e.g. "isRootService") to use as a filter when looking up ServiceReferences?
The best way is to use service registration properties
#Component
#Service
#Property(name = "service.id", value = "<some service unique ID")
class ChildServiceImpl1 implements Service{...}
When you look for some specific services you can use service filter:
bc.getServiceReferences(Service.class.getName(), "(service.id=<some value>)");
or if you like to use it in DS component as service reference:
#Reference(target = "(service.id=<some value>)", cardinality = ...)
private Service service;
If the AggregateServiceImpl is the only Service being used by other bundles, then it should be the only one you register.
From the code you have currently shown, we cannot tell if the AggregateServiceImpl class has dependencies on Service or the actual implementations.
If it has dependencies directly on other implementations, not the Service interface (as you have currently described it) the aggregate bundle should create the other implementation classes it requires directly and then register the AggregateServiceImpl as a Service.
If the other implementations need to be used elsewhere as well, then you should use properties (as you suggested) so consumers can distinguish between them. In this case, you still cannot use DS to construct your aggregate, since it doesn't have a dependencies on Service

how to implement a service layer in servlet application

Suppose I want to create a service layer for my web application which uses servlets,How should I go about this?(I am not using a web app framework..So,please bear with me).Should I implement it as a listener?The service is meant to do database access.That is,I should be able to call from my servlet
class MyServlet{
...
doPost(...){
...
MyEntity entity = dbAccessService.getMyEntity(someId);
...
}
}
Where the dbAccessService should deal with hibernate session,transactions etc.Previously I used to do all this inside dao methods, but I was advised that was not a good idea.
Any suggestions welcome
thanks
mark
Sample code snippet is given below
class DBAccessServiceImpl{
...
private MyEntity getMyEntity(Long id){
Transaction tx = null;
MyEntity me = null;
Session session = HibernateUtil.getCurrentSession();
try{
tx = session.beginTransaction();
return entitydao.findEntityById(id);
}catch(RuntimeException e){
logger.info("problem occurred while calling findEntityById()");
throw e;
}
}
...
}
Then create a listener to instantiate DBAccessService
class MyAppListener implements ServletContextListener {
#Override
public void contextInitialized(ServletContextEvent ctxEvent) {
ServletContext sc = ctxEvent.getServletContext();
DBAccessService dbservice = new DBAccessServiceImpl();
sc.setAttribute("dbAccessService",dbservice);
}
}
In web.xml add listener
...
<listener>
<listener-class>myapp.listeners.MyAppListener</listener-class>
</listener>
...
Assuming you do not want to introduce a framework, two options make sense (in my opinion):
define your service layer using stateless EJB session beans. You need an EJB container.
do it as always in OO languages, create an interface and a corresponding implementation:
Define an interface
public interface BusinessService {
abstract public BusinessObject performSomeOperation(SomeInput input);
}
And an implementation
public class BusinessServiceImpl implements BusinessService {
public BusinessObject performSomeOperation(SomeInput input) {
// some logic here...
}
}
You have several options for instantiating the service. If you start from scratch with a small application it may be sufficient to simply instantiate the service inside your web application:
BusinessService service = new BusinessServiceImpl();
service.performSomeOperation(...);
BTW: At a later time you may want to refactor and implement some abstractions around the Service instantiation (Factory pattern, dependency injection, etc.). Furthermore, in large systems there is a chance that you have to host the service layer on it's own infrastructure for scalability, so that your webapp communicates with the service layer via an open protocol, be it RESTful or Web Services.
However the future looks like, having a well defined interface defining your business functions in place, allows you to "easily" move forward if the application grows.
Response to your update:
I would not implement the service itself as a listener, this does not make sense. Nevertheless, your sample code seems to be reasonable, but you must distinguish between the Service (in this case DBAccessService) and the way you instantiate/retrieve it (the listener). The listener you've implemented plays in fact the role of a ServiceLocator which is capable of finding a certain services. If you store the instance of your Service in the servlet context you have to remind that the service implementation must be thread safe.
You have to be carefull to not over-engineer your design - keep it simple as long as you cannot foresee further, complex requirements. If it's not yet complex I suggest to encapsulate the implementation using a simple static factory method:
public final class ServiceFactory {
public static DBAccessService getDBAccessService() {
DBAccessService service = new DBAccessServiceImpl();
return service;
}
}
Complex alternatives are available to implement the ServiceFactory and nowadays some call it anti-pattern. But as long as you do not want to start with dependency injection (etc.) this one is still a valid solution. The service implementation DBAccessServiceImpl is accessed at one place only (the factory). As I mentioned before - keep an eye on multi-threading... hope this helps!
What you're suggesting is really no different to doing the session and transaction handling in a DAO. After all, your service class calls the DAO; to the client code, there is no difference.
Rather, i suspect that whoever told you not to put the session handling in the DAO was thinking that you should instead use Open Session In View pattern. Very simply, in its usual form, that involves writing a Filter which opens a session and starts a transaction before passing the request down the chain, and then commits the transaction (or rolls it back if necessary) and closes the session after the request completes. That means that within any one request, all access to persistent objects happens in a single transaction and a single session, which is usually the right way to do it (it's certainly the fastest way to do it).

Categories

Resources