View Full Version : Use one interface method and "hide" the rest
budrul
Jun 28th, 2011, 10:24 AM
Well, sometimes they say you that you have to use an EJB interface in your project for reusing some other's project code. Imagine the following EJB interface local or remote:
public interface SomeDifficultInterface
{
public DifficultBean1 getDifficultMethod1(DifficultBean5,DifficultBean6)
public DifficultBean2 getDifficultMethod2(DifficultBean7,DifficultBean8)
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
public DifficultBean4 getDifficultMethod4(DifficultBean11,DifficultBean1 2)
//...more of the same
}
You are in a new Project and they say you that you have to use the getDifficultMethod3() of that interface, of course for doing that at least you need
to include in your project the referenced classes DifficultBean3, DifficultBean9, DifficultBean10, That EJB its outside your .EAR, so perhaps you will have to make a context lookup or a @EJB injection.
My question is as follows: is there a way for using the getDifficultMethod3() method in a way that I dont have to import the rest of Classes in my project? I mean I dont want to add to my classpath the classes I do not use like: DifficultBean1,DifficultBean2,DifficultBean4,Diffi cultBean5 etc..
So, what I reaaly want is to call that method using my own interface:
public interface EasyInterface
{
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
}
dlmiles
Jun 29th, 2011, 06:17 PM
EJB projects can have "client JARs" which are meant to be the collection of stuff any EJB client needs to make used of the EJB interfaces their (the vendors) collection of method calls.
Are you saying there is some issue you have in using your vendors EJB client JAR with your project ? Can you explain what the issue/problem really is ?
There is nothing stopping you from trying to manually removing files from it for the things you application doesn't need to reference. But you have to wonder why do this ? The contents of *.class are not loaded into the JVM so consume no extra space at runtime.
But I have no idea of the effect of messing/editing the interface definition (the *.class) you are using at the client. At the end of the day the clients JARs exist to provide your application the ability to compile/link with the types used by the EJB interfaces. So it is probably theoretically possible to mess with them and have RMI (the serialization process used to invoke EJBs) continue to work.
You also need to consider the types used in the methods you keep and also the object graph of the types you pass in during invocation and the returned data.
What is the concern with dragging in the other types. If your client application is only using the interface, and the one method upon it. It should only be needing to import the types you use.
I would hope at runtime that a JVM doesn't need to conern itself too much with types used in interfaces it never uses. i.e. it knows this type exists (having read the *.class for the interface) but doesn't need to load it yet.
Do you have control of the EJB project? to make changes. I would guess not (from the tone of your demand).
On the server side you can provide other endpoints implementing your cut down interface, i.e. define a new interface with just this method exposed. It might even do a local EJB lookup and just delegate all methods to that other EJB.
budrul
Jun 30th, 2011, 04:01 AM
Let me explain better:
In my company we share a DEV websphere environment, there is a project in that server that perform the X functionality via EJB call. I need that X functionality (a call to a method of that EJB) in my project, but I cant change anything from that EJB, I cannont change its interface/implementation, of course I can use their EJB interface but its too complex, I must have to import many classes/jars only for calling that X method I want. So I was wondering if there is a way for calling that X method with a simplified interface:
public interface SomeDifficultInterface
{
public DifficultBean1 getDifficultMethod1(DifficultBean5,DifficultBean6)
public DifficultBean2 getDifficultMethod2(DifficultBean7,DifficultBean8)
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
public DifficultBean4 getDifficultMethod4(DifficultBean11,DifficultBean1 2)
//...more of the same
}
public interface EasyInterface
{
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
}
You can see that the method signature of getDifficultMethod3 is the same in both iterfaces so I think its possible to use an interface like Easyinterface so I dont have to add another classes like DifficultBean1,DifficultBean2,DifficultBean4 in my project. Perhaps I should use some kind of dynamic proxy or AOP I dont know. what do you think?
dlmiles
Jun 30th, 2011, 11:30 AM
So can you deploy your own EJB on the server side ? You can make your own interface, exposing the method you want and on the server it is just a delegate pattern that looks up the feature-full EJB to invoke that one method.
The new concern that comes from this is in the DTO (Data Transfer Objects). The types you pass in and the return type from the method. You need to fully understand the maximum theoretical object graph and include all those types in a new EJB client JAR ? Do you have the knowledge to actually do this ? If the EJB interface is provided by an external vendor then the usual answer would be no. Your application may break from upgrades in EJB client JAR.
You do have an EJB client JAR right (or are you having to work with the entire deployable EJB) ? And this has other dependancies ? What kind of dependancies does your EJB client JAR need ? If they are all inside you vendors package namespace, I don't understand your concerns. Just include them and save your efforts for something else.
I don't see how the notion of proxying can help you. The interface name and type and the DTO types are all important things that must largely stay the same for the RMI mechanism to work. So while trying to make it look pretty to your application usage might be possible, it doesn't help you on the mission of reducing the size of the EJB client JAR you need to include in your project if the RMI mechanism breaks. In short your application will compile but be unable to communicate effectively with the remote EJB interface.
Now it maybe possible to narrow the interface via some magic ... but you are still going to need to include all the JARs client side as you have to have the EJB client <> EJB server talking via RMI effectively using the correct types and interfaces... so it kind of defeats your main point right ? Doing this might be considered the Facade pattern to your new EasyInterface by using an underlying SomeDifficultInterface. But this doesn't remove your dependancies from the larger view of the client side codebase... Which is your goal right ?
The point here is to get any real benefit that meets your goals of simplified client side usage, you need to be able to deploy your own EJB server side or expose a Facade remote EJB interface http://en.wikipedia.org/wiki/Facade_pattern . That EJB is only a few files and a few lines, but maybe you don't have control of the server to do this ?
budrul
Jul 1st, 2011, 08:23 AM
Both EARs, mine and the other one that has the EJB function I want, are deployed in the same server so I see no use in duplicate the EJB in my side, I just must have to be able to call its interface in the way I want. But OK, perhaps it is not possible. What do you think about this approach?:
If I am able to make that EJB(the one that has the X functionality) to implement MY interface then I could inject that EJB and use my interface right?:
public EJBImpl implements SomeDifficultInterface,EasyInterface
{
public DifficultBean1 getDifficultMethod1(DifficultBean5,DifficultBean6)
public DifficultBean2 getDifficultMethod2(DifficultBean7,DifficultBean8)
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
public DifficultBean4 getDifficultMethod4(DifficultBean11,DifficultBean1 2)
//...more of the same
}
and EasyInterface is:
public interface EasyInterface
{
public DifficultBean3 getDifficultMethod3(DifficultBean9,DifficultBean10 )
}
Then I think it could be done... but the problem is that I cannont change the EJB, I have no rights, I cant make it to implement my interface changing the code... but perhaps there is some way to do it at Runtime.. I mean: you have 1 class that implements 1 interface.... is it possible to take an object of this class and force it to implement another interface (EasyInterface)?
dlmiles
Jul 1st, 2011, 12:01 PM
Delegate pattern, pseudo code (please fix before use!)
package com.mydomain.somenew.packagenamespace;
@Stateless
@Remote(EasyInterfaceRemote.class)
public class EasyInterfaceImpl implements EasyInterfaceRemote {
@EJB
private SomeDifficultInterface someDifficultInterface;
public DifficultBean3 getDifficultMethod3(DifficultBean9 difficultBean9,DifficultBean10 difficultBean10) {
return someDifficultInterface.getDifficultMethod3(difficu ltBean9, difficultBean10);
}
}
Now deploy that as a separate EJB that depends on the other.
Create your "EJB client JARs" by including at least the following types EasyInterfaceRemote , DifficultBean3 , DifficultBean9 , DifficultBean10 (plus any other types contained inside the theoretical object graphic within those types).
1) You are not modifying any existing code.
2) You are creating new EJB inside a new package namespace.
3) I believe this pattern in OOP terms would be a Facade pattern implement by way of a Delegation pattern.
Powered by vBulletin® Version 4.2.1 Copyright © 2013 vBulletin Solutions, Inc. All rights reserved.