EJB2 xdoclet #ejb.ejb-ref in session bean pointing to itself - java

I'm working now on migration from EJB 2.0 to 3.0.
Old session beans used xdoclets to configure some stuff.
I can understand almost all of them, but there is one thing that is bothering me.
Why do someone use #ejb.ejb-ref in way like in code below.
/**
* #ejb:bean name="SomeBean"
* local-jndi-name="com/my/jndi/SomeBean"
* view-type="local" type="Stateless"
*
* #ejb.ejb-ref ejb-name="SomeBean"
* view-type="local"
*
* ..some more stuff here
*/
public class SomeBean implements SessionBean {
// class body here
}
There is few more #tags in this xdoclet including some for configuring weblogic (#weblogic).
Is there some reason we may want to add reference to bean itself?
Second question, is this config still needed in ejb3?
I have this feeling that I read somewhere that this #weblogic tags may sometimes need to use this kind of reference but I just cannot find it one more time. Is it true?
#EDIT
After talk with one of the authors of such classes, i find out that such self-reference may be used when one of bean methods calls second method (which may have to require new transaction) by using reference to instance of class it's owns.
After upgrade it can be replaced by something like this below.
#Stateless
public class SomeBean implements IBeanLocal {
#EJB
IBeanLocal someBean;
// class body here
}
My confusion was mainly caused by some unnecessary uses of this kind of self-reference.
As pointed by Steve C, probably someone wasn't sure how to use this xdoclet feature.

First of all, the "local" view types imply that you're looking at EJB 2.1 code (not 2.0).
I agree that the #ejb.ejb-ref tag is curious. It would only be useful if it was using JNDI somewhere to look up another instance of the same type of session bean. And even then it's redundant because the ejb home objects are available in the bean's EJBContext object.
It's quite possible the original authors did not know what the ejb-ref was for. There was a lot of that going around at the time.
If there was an ejb-ref to another type of bean, then you would typically see a corresponding #weblogic.ejb-local-reference-description or #weblogic.ejb-reference-description which is used to generate the JNDI mapping information in the weblogic.xml file, linked by the ejb-name.
In any event, you would replace any of these lookup references with instance variables marked up with #EJB.
The complete xdoclet documentation (and source) is still available at (http://xdoclet.sourceforge.net/xdoclet/index.html), FWIW.

Related

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.

Ejb returns java.lang.NullPointerException

I am newbie in cdi and these are my first steps.
I have a bean in ejb module:
#Stateless
public class TestBean {
public String getIt(){
return "test";
}
}
I have a POJO in war module (I tried with #EJB and #Inject - same result)
public class SaveAction extends Action{
#EJB
private TestBean bean;
#Override
public void execute(){
....
String test = bean.getIt(); //HERE I GET java.lang.NullPointerException
...
}
}
Both war and ejb are inside ear. In log I see
EJB5181:Portable JNDI names for EJB TestBean:
[java:global/example.com/my-ejb/TestBean!com.example.TestBean,
java:global/example.com/my-ejb/TestBean]]]
From that I conclude that bean is initialized - but I can't find it. What am I doing wrong?
CDI and other dependency injection containers don't use magic! It's just ordinary java code that cannot do more or less than any other java code written anywhere. So it is impossible for a framework to do injection when an object is instantiated directly via new:
SaveAction action = new SaveAction();
// don't expect any injection has happened - it can't! no magic!
// action.bean is still null here!
The framework does not have any idea that an object like SaveAction has been instantiated. (Therefore it would be necessary to somehow inform the framework about the newly created object - but neither the constructor nor the 'new' statement do this! Just think one minute about how you would write such a framework code! It's not possible!* ).
To make injection work, the object must be created by the container instead! Otherwise it is NOT managed! (See also chapter 3.7 of the Web Beans specification (JSR 299)).
The best way to do this is to let the container inject the object into another already managed bean. It seems this just deferes the problem, but there are some already managed beans in your application, like the servlet!
Suggestion: Make your SaveAction CDI aware (e.g. annotate it with #Default) and let it be injected into your servlet!
Tutorials:
http://middlewaremagic.com/jboss/?p=1063
http://hudson.jboss.org/jenkins/job/JBoss-AS7-Docs/lastSuccessfulBuild/artifact/guides/developer-getting-started-guide/target/docbook/publish/en-US/html/helloworld.html
*) In theory it should be possible using aspect oriented programming or instrumentation to manipulate the constructors of beans to notify the container if they are invoked. But that's a very complex concept with many unsolved issues I think.

JMX MXBean Attributes all UNDEFINED - Spring 3.0.x/Tomcat 6.0

I've been trying to get a sample JMX MXBean working in a Spring-configured webapp, but any basic attributes on the MXBean are coming up as UNDEFINED when I connect with jconsole.
Java interface/classes:
public interface IJmxBean { // marker interface for spring config, see below
}
public interface MgmtMXBean { // lexical convention for MXBeans - mgmt interface
public int getAttribute();
}
public class Mgmt implements IJmxBean, MgmtMXBean { // actual JMX bean
private IServiceBean serviceBean; // service bean injected by Spring
private int attribute = 0;
#Override
public int getAttribute() {
if(serviceBean != null) {
attribute = serviceBean.getRequestedAttribute();
}
return attribute;
}
public void setServiceBean(IServiceBean serviceBean) {
this.serviceBean = serviceBean;
}
}
Spring JMX config:
<beans>
<context:component-scan base-package="...">
<context:include-filter type="assignable" expression="...IJmxBean" />
</context:component-scan>
<context:mbean-export />
</beans>
Here's what I know so far:
The element is correctly instantiating a bean named "mgmt". I've got logging in a zero-argument public constructor that indicates it gets constructed.
is correctly automatically detecting and registering the MgmtMXBean interface with my Tomcat 6.0 container. I can connect to the MBeanServer in Tomcat with jconsole and drill down to the Mgmt MXBean.
When examining the MXBean, "Attribute" is always listed as UNDEFINED, but jconsole can tell the correct type of the attribute. Further, hitting "Refresh" in jconsole does not actually invoke the getter method of "Attribute"- I have logging in the getter method to indicate if it is being invoked (similar to the constructor logging that works) and I see nothing in the logs.
At this point I'm not sure what I'm doing wrong. I've tried a number of things, including constructing an explicit Spring MBeanExporter instance and registering the MXBean by hand, but it either results in the MBean/MXBean not getting registered with Tomcat's MBean server or an Attribute value of UNDEFINED.
For various reasons, I'd prefer not to have to use Spring's #ManagedResource/#ManagedAttribute annotations.
Is there something that I'm missing in the Spring docs or MBean/MXBean specs?
ISSUE RESOLVED: Thanks to prompting by Jon Stevens (above), I went back and re-examined my code and Spring configuration files:
Throwing an exception in the getAttribute() method is a sure way to get "Unavailable" to show up as the attribute's value in JConsole. In my case:
The Spring JMX config file I was using was lacking the default-autowire="" attribute on the root <beans> element;
The code presented above checks to see if serviceBean != null. Apparently I write better code on stackoverflow.com than in my test code, since my test code wasn't checking for that. Nor did I have implements InitializingBean or #PostConstruct to check for serviceBean != null like I normally do on almost all the other beans I use;
The code invoking the service bean was before the logging, so I never saw any log messages about getter methods being entered;
JConsole doesn't report when attribute methods throw exceptions;
The NPE did not show up in the Tomcat logs.
Once I resolved the issue with serviceBean == null, everything worked perfectly. Regardless, +1 to Jon for providing a working demo, since there are literally 50 different ways to configure MBeans/MXBeans within Spring.
I've recently built a sample Spring based webapp that very cleanly enables JMX for latest versions of Spring, Hibernate and Ehcache.
It has examples for both EntityManager based access and DAO access (including transactions!). It also shows how to do annotation based injection in order to negate having to use Spring's xml config for beans. There is even a SpringMVC based example servlet using annotations. Basically, this is a Spring based version of a fairly powerful application server running on top of any servlet engine.
It isn't documented yet, but I'll get to that soon. Take a look at the configuration files and source code and it should be pretty clear.
The motivation behind this is that I got tired of all of the crazy blog posts with 50 different ways to set things up and finally made a single simple source that people can work from. It is up on github so feel free to fork the project and do whatever you want with it.
https://github.com/lookfirst/fallback

How to automatically create and inject a proxy of a missing dependency?

Given the following classes:
package com.acme;
public class Foo {
private Bar bar;
public void setBar(Bar newBar) {
this.bar = newBar;
}
}
#AcmeService
public interface Bar {}
and a Spring configuration file of:
<beans>
<bean id="foo" class="com.acme.Foo">
<property name="bar" ref="bar" />
</bean>
</beans>
when Spring's configuration phase runs, is it possible to do the following?
Catch the missing dependency exception (or detect that there is going to be one)
Discover that the missing dependency "bar" of bean "foo" is of type com.acme.Bar
Notice that Bar is an #AcmeService, and so we're going to handle it. Otherwise, the error can be considered fatal
Generate a proxy of type com.acme.Bar
Inject the Bar proxy into Foo, ensuring that method calls on Bar can be advised with Spring AOP just as if I had explicitly created the Bar proxy in the Spring config file and injected the proxy into the Foo bean.
I was initially drawn to BeanPostProcessor and BeanFactoryPostProcessor as a means to implement this, although upon reading the documentation I did not see an obvious way of doing precisely what I want.
In case you're wondering, the underlying use case is that I want to:
Replace all Spring context files with my service-layer bean definitions with a single context file that generates proxies of #AcmeService bean interfaces.
Advise invocations against those proxies to instead be invoked on interface mocks of the service layer bean proxies. (The kicker is that the mocks are defined at runtime by a remote system and are uploaded to this app for integration testing purposes. For my regular unit tests, I do the more sane thing of simply creating and injecting mocks as needed).
I have all of that working except for the whole "dynamically generate proxies" bit. Currently I have empty implementations of my service interfaces defined in my context file just so they can be injected and advised - but I'd rather not have so many empty interface classes generated and checked in. And lastly, I assume I need to generate these proxies as I do not know how to advise attempted invocations on null dependencies.
OK, there's a number of things in here to talk about.
Firstly, I don't think you'll be able to do exactly what you're asking. In particular, if you have <property name="bar" ref="bar"/> and there is no bean definition for bar, the bean initialization will fail, and I don't think you can intercept that easily. You could, of course, write your own subclass of the BeanFactory itself, but that's not something to be taken lightly.
The closest existing mechanism to what you're asking for is auto-wiring. Take a look at AutowiredAnnotationBeanPostProcessor. You could use this as a guide for writing your own BeanPostProcessor which looks at every bean as it's instantiated by the container, looking for properties which are of types which in turn have the #AcmeService annotation. When it finds one, it can generate a proxy for that type and inject it.
That brings us on to the proxy generation itself. The place to look for that is ProxyFactory. This allows you to generate objects at runtime that implement any interface or extend any class, whilst attaching advisors/interceptors. These interceptors can do all the work - the proxy doesn't have to have anything "behind" it if you don't want to.
With this approach, you wouldn't need the "hanging" <property name="bar" ref="bar"/> entry in your config - the presence of the property in Foo would be enough to trigger the process.

Auto-cast Spring Beans

Is there a way to auto-cast Spring beans to the class defined in the application context XML? I'd like to avoid putting type information about the beans in 2 places.... in the xml configuration file and also in the code as a cast.
For instance, given this config file
<bean id="bean-name" class="SimpleSpringBean" scope="prototype">
<property name="myValue" value="simple value"></property>
</bean>
Can I call ApplicationContext.getBean("bean-name") in such a way as to avoid directly casting the return type to SimpleStringBean. I know I can also call ApplicationContext.getBean("bean-name", SimpleSpringBean.class) to avoid the cast itself, but I still have the type info in 2 places.
It seems that Spring can get the class info (ApplicationContext.getType) or by getting the type from the bean itself, but no way to automatically cast the type without programmer intervention.
I agree with Sii, you should avoid calling getBean as much as you can. Just wire your beans to classes that depends on them.
Still, if you have a single class that holds the application context, you can provide a wrapper generic method like the following:
class MyContextHolder{
ApplicationContext appContext;
......
#SuppressWarnings("unchecked")
public static <T> T getBean(String beanName)
{
return (T)appContext.getBean(beanName);
}
}
Then you can call it without casting
MyClass mc = MyContextHolder.getBean("myClassBean");
The answer is you shouldn't be using ApplicationContext.getBean() at all if it's possible, and bear with the one place you have to in the bootstrap code. (Generally, you should never need to use getBean() outside of your application's entry points.)
Also, what you're asking is likely impossible in the Java language at all. Casting is a compile-time feature, combined with a runtime check. The return type of getBean() simply must be known at compile time. Even if Spring can determine the type of an object, it can't change its own method signatures at runtime.
Another thing is that even if this were possible, the feature wouldn't be all that useful. Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class.
Another approach I also use is autowiring the bootstrapping class using:
public class Main {
#Autowired FooFacade foo;
#Autowired BarFacade bar;
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("appCtx.xml");
AutowireCapableBeanFactory bf = ctx.getAutowireCapableBeanFactory();
Object main = bf.createBean(Main.class,
AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT,
false);
((Main) main).run();
}
private void run() {
foo.doBootstrapStuff();
bar.doMoreBootstrapStuff();
}
}
(Code done from memory. Might only work if you have the Spring context configured to process wiring annotations, in that case making setters for foo and bar should work.)
The main reason for getBean being untyped is the compatibility of Spring (up to version 2.5.x) with Java 1.4. Spring 3.0 will drop that and thus offer typed getBean method then.
Nevertheless you should avoid looking up beans directly and minimize its usage as far as possible.
What if I use Spring as an object factory that my application uses extensively.
That is, instead of writing a bunch of classes that already inherit or wrap around
known Java classes I just decide to move all that into an xml file to cut down on
lines of Java code. This will mean many lines of xml but I won't need to make
skeleton Java classes which I inject with Spring or autowire. Thus making the lines
of Java code less.
For this reason and still as I am new to Spring I have just as stated in previous
posts used static Java methods which wrap around the getBeans().
I have worked with Spring but it is still new to me so forgive my question.
"Because Spring AOP is implemented using dynamic proxies, you nearly always want Spring to hand you an instance of an interface the bean implements (which could be an AOP proxy), not of the implementation class"
So there is no way to get a dynamic proxy using getBean(), then whats the best practice if there are no interfaces and its a stand alone driver class to be executed?

Categories

Resources