I have a maven client project that i run as maven test. First thing i do in the junit test is a lookup using the jndi string. Here i receive a stateless bean proxy which is cast to a remote interface. As soon as i call a method from the interface (like saving some domain objects wich uses a data access object wich uses jpa) i receive the exception
javax.ejb.NoSuchEJBException: No such EJB[appname=,modulename=someName,distinctname=,beanname=SomeBean]
The documentation says: "A NoSuchEJBException is thrown if an attempt is made to invoke a business method on a stateful session or singleton object that no longer exists". The thing is that the bean is stateless and not stateful or a singleton. I'm also quite sure that the jndi string is correct, because if i make the same lookup and persistence-method-call in the main method of the client project (run as maven build with "install jboss-as:deploy") everything works fine.
Any suggestions how i could use the persistence methods from the proxy when testing? Some colleagues have a similar setup and it works for them without Arquillian or so.
I don't know why but it works now. What I did was removing the getter-method for the EntityManager within the abstract generic DaoBean that all DaoBeans inherit. Having the getter was suddenly shown as an Error while executing the client (it wasn't shown as error before).
Related
Weired world... let me try:
I have the follwing mavenized setup:
- Springboot (1.5.5.RELEASE)
- Hibernate (5.0.9.Final; I do know there is newer variants but I stick with what I have right now)
- ExtJs (6.0.0)
- IntelliJ (2017.3)
I do partly get running into an Hibernate Exception:
2018-11-20_15:04:58.007 [http-nio-8081-exec-7] [ERROR] o.a.c.c.C.[.[.[/].[dispatcherServlet]:181 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.hibernate.HibernateException:
Could not obtain transaction-synchronized Session for current thread] with root cause
org.hibernate.HibernateException: Could not obtain transaction-synchronized Session for current thread
at org.springframework.orm.hibernate5.SpringSessionContext.currentSession(SpringSessionContext.java:133)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:697)
...
This does not happen on all threads! Partly the requests from ExtJs go through, Partly they don't. But would they not open a transaction on the webserver side?
I do have an Interceptor; well a web Interceptor implementing org.springframework.web.servlet.HandlerInterceptor
Within the interceptor's preHandle method I do call a Service in order to check if a user is logged in and do some rights management handling.
The called #Autowired service fails. I thought the fact of accessing an #Autowired service method takes care of session/transaction handling.
Well, this was the scenario having my project manually created and run with a java-8 (java 8 sdk; not 9, not 10, not 11) command like from the console:
mvn clean package -DskipTests && java -jar target/MyBuild.jar application-local.properties
I just observed that the login consists of three request from browser to the backend. These three are all handled in separate threads by the backend.
When running the project within IntelliJ it all works fine. Ok, IntelliJ most likely does not jar the application and builds its own startup command.
But exactly that brings me out of rhythm due to the fact that we do process the code through a deployment / CI pipeline where we manually build the project.
And that is where it fails :-(
Amendment:
I changed everything to run with JPA instead of Hibernate (well it is still hibernate in the background). Just as 'M. Deinum' suggested.
Now, the problem still exists.
Two things I somewhat extracted.
In my Interceptor I do have some logging calls which ask the EntityManager for a hibernate-session (entityManager.unwrap( Session.class )).
This is the point where now.
So it seems that on the preHandle(...) of my interceptor there is sometimes no current session active. I am stating 'sometimes' since there are calls to the Interceptor when it works.
The exception comes as following now:
java.lang.IllegalStateException: No transactional EntityManager available
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:272)
at com.sun.proxy.$Proxy117.unwrap(Unknown Source)
at com.mypackage.dataaccess.DataAccessImpl.getCurrentSession(DataAccessImpl.java:89)
at com.mypackage.dataaccess.DataAccessImpl.queryByHQL(DataAccessImpl.java:382)
Ok. I ended up noting all Spring web controllers to have an #Transactional (where DB usage is given.)
That works.
From my understanding it does not matter where to put the #Transactional annotation as long as the method/owning Object is invoked through spring's #Autowire mechanism.
If I want something to run under the transactional behaviour I would annotated with it on the closest scope possible.
That's how I would decide where to put the #Transactional
At the end it does work but I am not satisfied with the solution.
If anyone could clarify the behaviour and/or my understanding let me welcomely know :-)
I have a webapp on one Glassfish server (front-end) and an EJB 3.1 app (back-end) on another Glassfish server. The webapp communicates with the EJB 3.1 via remote invocation.
I would like to pass context data (user data i.e.) without having to define it as an input parameter of each business operation.
I have one idea, but not sure it will work: use a ThreadLocal to store data, but the ThreadLocal will only be available on one server (meaning JVM) => use the InvocationContext object and create interceptor to add user data to the ContextData Map.
What do you think about it? Any other ideas are more than welcome! ;-)
UPDATE
After first answer, I googled it a little bit and found the annotation #CallerPrincipal.
How can I set this object before the remote invocation?
The container will already handle this so you don't have to code it yourself.
In your EJB, you can access the EJBContext, which has a getCallerPrincipal() method which will give you the callers identity.
I'm using mockejb framework to mock entity beans in memory, I make a lookup, mockejb brings me a proxy for the real entity. That's working.
But I needed to get a Session Bean from the container JNDI to "understand" that. I mean, when the Session Bean make a lookup to the Entity Bean, I want it to receive the bean I've mocked, not a bean from the database.
I can't mock this Session Bean because inside the method I'm trying to mock, there's a lookup to the entity bean so, I need this method to execute normally but to receive the mocked bean when lookup.
[UPDATE]
Informations about my development environment:
I'm using IBM RSA 7.5, IBM Websphere 6.1,
I have a Web Test Project that runs in-container with Cactus, the last libs on my classpath are:
cactus-1.7.2.jar
cglib-nodep-2.1_3.jar
commons-httpclient-2.0.2.jar
commons-logging-1.0.4.jar
powermock-easymock-1.3.9-full.jar
junit-3.8.1.jar
mockejb.jar
Obs.: I've already changed to the latest powermock version with jUnit4, and tried to use EasyMock 3.0 only, and also tried EasyMock 2.x with its class extensions. None of these worked. What really intrigues me is this DefaultInstantiator configuration mentioned on EasyMock docs: http://easymock.org/EasyMock2_4_ClassExtension_Documentation.html. I wondered if that's my case (not supported JVM) and I couldn't make it work.
Thanks for helping.
"I can't mock this Session Bean because inside the method I'm trying to mock, there's a lookup to the entity bean so,"
Can't you use something like PowerMock to 'fake' the lookup? Like with a replace of methods etc.
Here is something i came across lately:
http://dave00ster.blogspot.com/2011/07/powermock-static-method-replace.html
Hope this helps,
dave00
I have a stateless session bean and a standalone-java-program acting as a client. The bean method executes just fine when the interface is marked #Remote. However,when I mark that interface with #Local instead of #Remote, I get the following Exception.
[java] javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Could not find InvokerLocator URL at JNDIaddress "chapter1/HelloUserBean/local"; looking up local Proxy from Remote JVM?]
But I expected even the latter to work, since it is the same computer that the code executes in.
Seeing this behavior, I am assuming that, the Application-Server and the Standalone-Java-Program use different JVM instances and not a single JVM instance and so this client can access only through a remote interface.
Is that assumption correct ?
Thanks !
Yes, it is correct.
#Local interfaces are to be used only within the same application-server. The application server starts one JVM instance, and your standalone client starts another.
I'm mantaining a EJB 2 CMP legacy app runing on a JBoss 4.0.4 GA application server with deployed entity/stateless session beans. All the EJB boilerplate code is generated via XDoclet from the EntityEJB/EntityEJBManager annotations.
I've noticed that when my GUI client invokes the facade create method, I have lots of cases of EJBException in my server log with the "Reentrant method call detected" message, which rollbacks the transaction.
What does this Exception means? How can I avoid having such error (which unfortunately, I wasn't able to reproduce yet)
Update: Found this link that explains what is meant by reentrancy, however, seems to me that it says my app cannot be accesed concurrently?
I've seen this before where EJB1 calls EJB2 which calls back to EJB1 within the container as part of the same transaction.
You can tell the container to allow this by marking EJB1 as reentrant which will allow it to be accessed multiple times in the same transaction.
This is done in the deployment descriptor with the following tag:
<reentrant>True</reentrant>
There should be a corresponding EntityEJB annotation that XDoclet can use to generate this for you.
we just came across the same problem and our solution was two-fold. Firstly we ensure that none of ejb's had transaction attributes of NotSupported within our ejb-jar.xml. We then used "instance per transaction" as our optimistic locking strategy. It's a bit of a belt-and-braces approach, but it works
It does mean that the Entity bean in question cannot be accessed concurrently, which makes sense since it would likely corrupt the data.