#Specializes for EJB - ejb

I'm trying to specialize an EJB. I have
package com.foo.core;
#Stateless
public class MyFacade { }
and
package com.foo.extension;
#Specializes
#Stateless
public class MyFacade extends com.foo.core.MyFacade { }
In my opinion, this should work, because the meaning of #Specializes is, that CDI should forget about the core-class and instead use the specialized class. I also found this bug https://issues.jboss.org/browse/WELD-1451 which indicates, that it is possible to specialize an EJB.
But if i try to deploy my application (I'm using Weblogic 12.1.3), I always get
weblogic.utils.ErrorCollectionException: There are 1 nested errors:
weblogic.j2ee.dd.xml.AnnotationProcessException: Duplicate ejb name
'MyFacade' found: annotation 'Stateless' on bean class
com.foo.core.MyFacade and annoation 'Stateless' on bean class
com.foo.extension.MyFacade
Am I doing anything wrong?
Thanks!

The exception message you quoted is caused by a name conflict, which is not directly related to CDI at all: each EJB can be addressed by a number of different JNDI names, and some of them (e.g. java:module/MyFacade) only include the simple class name, not the package name. So you cannot have two EJBs with the same name in different packages.
Adding CDI and #Specializes may prevent the specialized EJB from showing up in the CDI container, but it is still an EJB.
You can try to rename your derived class - this should solve the duplicate name issue, but I'm not sure it will solve your overall problem.

Related

How Can I make Spring-MVC #PropertySources load first, before any other configuration

I have a spring-mvc application that is using java configuration, not xml. There are #Configuration annotations sprinkled through several files. In particular, there is a #PropertySources annotation in one file in a class that implements WebMvcConfigurerAdapter. There are two classes which contain an #Autowired Environment variable. One of these classes is itself a #Configuration class, and I would like it to have access to the fully-loaded Environment at the time it runs.
This isn't happening. When this code executes, the Environment is still null. I've tried reordering the #ComponentScan packages, tried moving the #PropertySources annotation, and nothing has helped me load the property sources in time.
I want this to happen first, before any other configuration.
What must I do to make it so?
UPDATE: After trying many things, including the Order annotation, I find the problem seems to be not so much that the #PropertySources are being loaded too late as that a class I have that is derived from org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer is being loaded too soon. Nothing in my code even references this class but Spring is somehow deciding that this, above all other classes, must be initialized first. No amount of messing around with #Order seems to change this. This in spite of the javadocs, which indicate that the behavior I want is the default:
Caveats
Subclasses of AbstractDispatcherServletInitializer will register their
filters before any other Filter. This means that you will typically
want to ensure subclasses of AbstractDispatcherServletInitializer are
invoked first. This can be done by ensuring the Order or Ordered of
AbstractDispatcherServletInitializer are sooner than subclasses of
AbstractSecurityWebApplicationInitializer.
You can use ContextInitializer, catch the moment when Boot prepared its environment and "inject" your property source programmatically as you want.
If you have a ConfigurableApplicationContext then it provides a ConfigurableEnvironment, which contains the propertySources as a list. If you want your PropertySource to rule all above the others than add it as first. If you want to place it to a special position then you can add it before an other, identified by its "name".
public class ConfigInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext ctx) {
// rule over all the others:
ctx.getEnvironment().getPropertySources().
addFirst(new ResourcePropertySource("file:/etc/conf/your_custom.properties"));
// rule over application.properties but not argument or systemproperties etc
ctx.getEnvironment().getPropertySources().
addBefore("applicationConfig: [classpath:/application.properties]",
new ResourcePropertySource("classpath:your_custom.properties"));
// names can be discovered by placing a breakpoint somewhere here and watch
// ctx.getEnvironment().getPropertySources().propertySourceList members,
// each has a name ...
}
}
You can bring into play this class by:
registering it in the application.properties :
context.initializer.classes=a.b.c.ConfigInitializer
or from application start :
new SpringApplicationBuilder(YourApplication.class).
initializers(new ConfigInitializer()).
run(args);
By the way this is a proper way to inject more of your custom properties, like properties coming from a database or a different host etc...
Not that I am an expert in Java config but maybe:
Spring 4 utilizes this feature in its #PropertySource annotation. To
remind you, #PropertySource annotation provides a mechanism for adding
a source of name/value property pairs to Spring's Environment and it
is used in conjunction with #Configuration classes.
Taken from: http://blog.codeleak.pl/2013/11/how-to-propertysource-annotations-in.html
Are you using #PropertySource or #PropertySources?
Have You tried 'order' property for spring bean initialisation?

Spring 3.2 #ControllerAdvice Not Working

I am having trouble getting #ControllerAdvice to work. I updated my namespace location, which were 3.1 in my xml files. I moved the class with the controller to the same package as the controller. I am using 3.2.0 release jars. If I put the #ExceptionHandler annotation in the controller code, it works, but not in a separate class with the #ControllerAdvice. When the #ControllerAdvice class fails, I get my uncaught exception handler view. Anyone have ideas on how to trouble shoot this one?
If you use classpath scanning, probably you have to add new include filter to your <context:component-scan> element:
<context:include-filter type="annotation"
expression="org.springframework.web.bind.annotation.ControllerAdvice" />
Default scanning does not lookup this annotation, following spring-context-3.2.xsd for component-scan:
"Scans the classpath for annotated components that will be auto-registered as Spring beans. By default, the Spring-provided #Component, #Repository, #Service, and #Controller stereotypes will be detected."
For this problem, The first thing is confirming your config,
You need make sure that the #ControllerAdvice Class under your component-scan base package.
Make suer you use <mvc:annotation-driven/> in your spring-servlet.xml. or have #EnableWebMvc in your #ControllerAdvice Class
When you have the config right, the ControllerAdvice should already work, Now you said You got your uncaught exception handler view. I guess you got that in your InegrationTest, And you used mockMvc to test that, If so, you need put #WebAppConfiguration and build mokcMvc as follow:
#Autowired
private WebApplicationContext wac;
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
Using standaloneSetup(controller) will not work because lack of WebApplicationContext.
There is no extra configuration required. It should just work. Look at this link for more details. This provide very simple example:
https://javabeat.net/exception-controlleradvice-spring-3-2/
https://javabeat.net/controlleradvice-improvements-spring-4-0/
I had this same problem, in my case the problem was that there was a dependent library that had inside it a class with the #ControllerAdvice and #Order(Ordered.HIGHEST) annotation, to solve the problem I added the #Order(Ordered.HIGHEST) annotation in my classe, and now it works.
Since my exception class is in the same controller package spring gave my class higher priority even though both classes have the same #Order(Ordered.HIGHEST)
#ControllerAdvice
#Order(Ordered.HIGHEST)
public class RestResponseEntityExceptionHandler
extends ResponseEntityExceptionHandler {
I struggled with the same problem where my #ControllerAdvice class would not load while unit testing REST controllers' exceptions. If you are using spring boot (version 4) then you can use additional methods added by spring to load controller advice classes in standalone setting up your controllers.
mockMvc = MockMvcBuilders
.standaloneSetup(new YourRestController())
.setControllerAdvice(new ControllerAdviceClass())
.build();
This will straight-away initialize your controller advice class and your Junit test should be able to jump in to #ExceptionHandler methods defined in your controller advice class.
For me, #ControllerAdvice was not working at all cost. Even adding #EnableWebMvc or #WebAppConfiguration didn't make any change.
The way I was able make it working was,
adding #ExceptionHandler methods for my AbstractController class, the class that all the other controllers are extending upon.
I think #ControllerAdvice is supposed to do the same thing, i.e. compile the #ExceptionHandler methods defined under the class specified by #ControllerAdvice, into a common place where every controller can refer from. But unfortunately it was not working for me.
I solved it by defining ControlAdvice class in Configuration beans as shown below:
#Primary
#Bean
public RestResponseEntityExceptionHandler restResponseEntityExceptionHandler (){
return new RestResponseEntityExceptionHandler ();
}

Per-Data store inheritance strategies in DataNucleus JDO?

I interface with two data stores, one of them is RDMS and the other one is LDAP. What I want to do is to have a hierarchy persisted using "superclass-table" in the RDBMS and "complete-table" in LDAP.
Is such a thing possible? That is, can you specify multiple inheritance strategies, separately for each data store in the *.orm files or am I forced to use a single inheritance strategy?
I couldn't find this information in the documentation of DataNucleus, they only thing I'm sure of is that you can put inheritance elements in an .orm file instead of the .jdo but that still doesn't answer my question...
The hierarchy is rather simple and consists of an abstract class and several subclasses like this:
abstract class Foo implements IFoo
{
...
}
class Foo1 extends Foo
{
...
}
class Foo2 extends Foo
{
...
}
...
I tried to configure inheritance in the two *.orm files AND in the .jdo file (having in mind that it's going to get overriden by the former) but I get an exception
Caused by: org.datanucleus.metadata.InvalidMetaDataException: Class "...Foo1..." has been specified with an inheritance strategy of "superclass-table", yet no superclass exists or none exists with its own table!
at org.datanucleus.metadata.AbstractClassMetaData.validateUserInputForInheritanceMetaData(AbstractClassMetaData.java:903)
at org.datanucleus.metadata.ClassMetaData.populate(ClassMetaData.java:214)
at org.datanucleus.metadata.MetaDataManager$1.run(MetaDataManager.java:2393)
at java.security.AccessController.doPrivileged(Native Method)
at org.datanucleus.metadata.MetaDataManager.populateAbstractClassMetaData(MetaDataManager.java:2387)
at org.datanucleus.metadata.MetaDataManager.populateFileMetaData(MetaDataManager.java:2224)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.loadMetaDataForClass(JDOMetaDataManager.java:741)
at org.datanucleus.jdo.metadata.JDOMetaDataManager.getMetaDataForClassInternal(JDOMetaDataManager.java:353)
at org.datanucleus.jdo.metadata.JDOMetaDataManager$MetaDataRegisterClassListener.registerClass(JDOMetaDataManager.java:184)
at javax.jdo.spi.JDOImplHelper.registerClass(JDOImplHelper.java:376)
I then tried to remove the inheritance elements from the .jdo but the enhancer fails with the following message:
Class "...Foo1..." has been specified to use an inheritance strategy of "superclass-table", persisting to the table of class ...Foo..., however this class doesnt have a discriminator specified.
The individual configurations are correct (new-table with discriminator at base-class and superclass-table at subclasses for the first case and complete-table only at base-class for the second).
You can put that information in the orm file, yes, and indeed that does answer your question since you have one ORM file for RDBMS, and one for LDAP. So package-rdbms.orm, and package-ldap.orm, and then simply set persistence property "javax.jdo.option.Mapping" to either "rdbms" or "ldap". Simple

javax.ejb.EJBException: Illegal non-business method access on no-interface view

I'm using EclipseLink on GlassFish 3.1.1 and I'm trying to understand this exception:
javax.ejb.EJBException: Illegal non-business method access on no-interface view
at org.mycompany.myproject.session.__EJB31_Generated__MyBeanFacade__Intf____Bean__.getEntityManager(Unknown Source)
at org.mycompany.myproject.session.AbstractFacade.edit(AbstractFacade.java:28)
at org.mycompany.myproject.controller.EditMyBeanServlet.doPost(EditMyBeanServlet.java:199)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
Notice that the stack trace indicates that the problem is triggered in the Netbeans generated AbstractFacade.getEntityManager method.
Any idea what the heck is going on or any tips to troubleshoot? I'm guessing that either the transaction or caching state in the EJB is weird when this happens because sometimes calling the edit method works fine. I'm calling the EJB methods from a Servlet. The exception occurs when trying to save changes to an entity.
The error you get most likely indicates that your code is trying to call the protected method anyway. This is not allowed for no-interface views on an EJB. You are only allowed to call public methods.
There's a small mismatch here between the normal Java class rules and the EJB rules. For a no-interface view, a proxy is created based on the original class type (typically a dynamic sub-class of it). This thus means that protected and package private methods are visible for code in the same package, and as far as the Java compiler is concerned, your code is allowed to call those.
But as mentioned, this is not allowed by the EJB rules, and thus an exception is thrown.
You can reproduce this easily by injection a bean like the following:
#Stateless
public class FooBean {
public void callMe() {
}
protected void doNotCallMe() {
}
}
Inject this somewhere (e.g. Servlet in same package) and try to call doNotCallMe(). You'll see the same exception. Call callMe() and everything will be fine.
I think I may have found a solution and possibly a bug in third party software. It seems like GlassFish 3.1.1 / EJB 3.1 / EclipseLink can't handle method overloading correctly. I've got a method defined in my EJB named edit that overloads (not overrides) the method from the parent abstract class. There is a method named edit in the abstract parent of the EJB that takes a generic type and then I've got a method named edit in the EJB which takes a List. If I rename the method to something else so that it is no longer overloading then the exception goes away!
Code:
public abstract class AbstractFacade<T> {
protected abstract EntityManager getEntityManager();
public void edit(T entity) {
...
and
#Stateless
public class MyEntityFacade extends AbstractFacade<MyEntity> {
protected EntityManager getEntityManager() { return em; )
public void edit(List<MyEntity> entities) {
...
Note: I noticed if I make the getEntityManager method public instead of protected I'll get a TransactionRequiredException instead of an EJBException.
What is weird is i had same problme with on inner class of my EJB.
While trying to call private method of parent or accessing on injected EJB, i faced some problems.
I had visibility on most of things but finally a runtie, things goes wrong.
Finally, i decided to retrieve my parent class throught JNDI, thus i could call public method without troubles. Meanwhile i could call still private methods on my parents class, i still have to remember that it will fail.

Passing state between EJB methods / #RequestScoped and #Stateless

I have a #RequestScoped CDI bean that I want to turn into an EJB to get declarative transactions. (I'm on EJB 3.1, Java EE 6)
Currently, I am passing state between subroutines, under the assumption that the instance is only used in a single request. If I add #Stateless now that assumption would change.
For example, I want to do something like
#Stateless
#Named
#RequestScoped
public class Foo {
private String var1; // can't use instance vars in #Stateless?
private String var2;
public void transactionForRequest() {
var1 = value;
var2 = value;
....
subroutine();
}
}
I assume the above doesn't work- is that correct?
I am contemplating two alternatives:
Use #Stateful instead of #Stateless, along with #Named and #RequestScoped.
Keep #Stateless and use EJBContext.getContextData map to replace instance variables.
Which is better? And is there some other alternative I'm not thinking of? (Besides wait for Java EE 7 or switch to Spring. :-))
While #Stateless, #Singleton and #MessageDriven can have scoped references injected via #Inject, they cannot be #RequestScoped or any other scope. Only the #Stateful model is flexible enough to support scopes. In other words, you can annotate the #Stateful bean class itself as #RequestScoped, #SessionScoped, etc..
In simple terms #Stateless, #Singleton have fixed "scopes" already. #Singleton is essentially #ApplicationScoped and #Stateless would perhaps be some made-up scope like #InvocationScoped, if that existed. The lifecycle of an #MessageDriven bean is entirely up to the Connector that drives it and is therefore also not allowed to have user-defined scope.
See also https://stackoverflow.com/a/8720148/190816
I would go with SFSB instead of SLSB. You want to hold a state, so for me this is the most important information - this is a job for Stateful EJB.
Also I don't think that EJBContext#getContextData() would help you. As far as I remember, it's only valid for a duration of a call. Therefore, each invocation of a method on your EJB will create new context data map (at least it's what I would expect.)
If you are using Stateless beans then you are responsible for any state-management and you would normally do this in the web-app layer using HttpSessions. And yes, you can't use instance variables as stateless beans are pooled.

Resources