Class Cast Exception between Spring Bean and EJB 3 - Jboss7 - java

I have an Spring Controller with a EJB injected. I can inject this EJB using spring proxy:
<jee:local-slsb id="procedimentRepositoryBean"
jndi-name="java:global/sedeib/sedeib-ejb/ProcedimentServiceFacade"
business-interface="es.caib.sedeib.service.facade.ProcedimentServiceFacade"/>
Both uses the same DTO, and when the EJB (procedimentServiceFacade) returns a filled DTO the spring controller try to Cast the DTO to the same DTO. It throws a ClassCastException:
#Controller
#RequestMapping("/prova/")
public class TestController {
#Autowired
private ProcedimentServiceFacade procedimentServiceFacade; //EJB Proxy INJECTION
#RequestMapping(value = "test", method = RequestMethod.GET)
#ResponseBody
public ProcedimentDTO test(){
ProcedimentDTO dto = procedimentServiceFacade.findById(1L).orElse(new ProcedimentDTO());
return dto;
}
}
Stack trace:
Caused by: java.lang.ClassCastException: class es.caib.sedeib.service.model.ProcedimentDTO cannot be cast to class es.caib.sedeib.service.model.ProcedimentDTO (es.caib.sedeib.service.model.ProcedimentDTO is in unnamed module of loader 'deployment.sedeib.ear' #4fd1ef7f; es.caib.sedeib.service.model.ProcedimentDTO is in unnamed module of loader 'deployment.sedeib.ear.sedeib-back.war' #33adbd6e)
at deployment.sedeib.ear.sedeib-back.war//es.caib.sedeib.back.controller.TestController.test(TestController.java:23)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:181)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at deployment.sedeib.ear.sedeib-back.war//org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
... 52 more
I read here that it could happen because the spring beans and the EJB are loaded by diferents class loaders. In old Jboss versions, this is solutioned by fixing a class loader with this config:
<class-loading>
<loader-repository>
some-name:loader=name
<loader-repository-config>java2ParentDelegation=false</loader-repository-config>
</loader-repository>
</class-loading>
But it seems deprecated for Jboss7. Are there any way for have the same class loader on both contexts (spring and EJB) ?
Environment:
OpenJdk11
Jboss7.2
EJB3
Spring 4.3.19

Related

Null pointer exception thrown in Autowired service class when I used JWT Authentication

I am creating the jwt authentication for a different role than here showing a null pointer exception. but when this URL I paste on the web security configuration class with the antmatcher method the API works fine but it shows an error in pre-authorize when I used it.
This is the Controller class
Controller Class Image
package com.shashank.controller;
.........
#RestController
#CrossOrigin
public class StudentController {
#Autowired
StudentService studentService;
#GetMapping("/api/student/stu")
#PreAuthorize("hasRole('User')")
private List<Student> getAllUStudent(){
System.out.println("Get Call");
return studentService.getAllStudent();
}
This is the Error in console
Error showing in Postman
java.lang.NullPointerException: Cannot invoke "com.shashank.service.StudentService.getAllStudent()" because "this.studentService" is null
at com.shashank.controller.StudentController.getAllUStudent(StudentController.java:28) ~[classes/:na]
Are you annotating your service class?
Spring uses component scanning to find the classes that it needs to auto-wire and insert into classes for IoC. Basically, Spring is going to scan the project's classpath (or paths you specified), find all of the #Component classes and make them available for auto-wiring. So if you forget to annotate a class it will not be auto-wired and when you try and use it you will get a null and a NullPointerException.
#Service, #Repository and #Controller are all specializations of #Component, so any class you want to auto-wire needs to be annotated with one of them.

How to autowire feign client (for external API) in a test?

I've written a simple Feign client, for calling an external API (running on a different server):
#FeignClient(
name = "test-service",
url = "https://some-test-server.com/api"
)
public interface TestClient {
#RequestMapping(method = RequestMethod.POST, value = "/test")
TestResponse test(TestRequest request);
}
I wrote some simple bean classes, TestRequest & TestResponse to model the request / response - I'm expecting them to be serialized & deserialized as json.
I want to just test that its able to make the HTTP call and receive a response, so I wrote a test:
#SpringBootTest
#EnableFeignClients(clients = TestClient.class)
class ClientApplicationTests {
#Autowired
private TestClient client;
#Test
void contextLoads() {
System.out.println(client.test(TestRequest.builder().foo("foo").build()));
}
But Intellij warns me that no Beans were found to autowire TestClient, and running this gives a similar exception:
java.lang.NoClassDefFoundError: org/springframework/cloud/context/named/NamedContextFactory$Specification
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[na:na]
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
at org.springframework.cloud.openfeign.FeignClientsRegistrar.registerClientConfiguration(FeignClientsRegistrar.java:410) ~[spring-cloud-openfeign-core-3.1.3.jar:3.1.3]
What am I doing wrong?
Try giving your Feign client class name in this format and check whether this works,
#EnableFeignClients(basePackageClasses=com.abc.xxx.client.TestClient.class)
This parameter accept single or multiple class name. You can also give the base package of the same,
#EnableFeignClients(basePackages = {"my.external.feign.client.package", "my.local.package"})
From the javadoc of #EnableFeignClients:
Scans for interfaces that declare they are feign clients (via FeignClient #FeignClient). Configures component scanning directives for use with org.springframework.context.annotation.Configuration #Configuration classes.
Generally this is placed on a #SpringBootApplication annotated class so that your Feign clients are available in production as well as your #SpringBootTest's.
If you really want to enable your Feign client only in your test, it should look something like this:
#SpringBootTest
class ClientApplicationTests {
#EnableFeignClients(clients = TestClient.class)
#Configuration
protected static class ClientApplicationTestsConfig {
}
#Autowired
private TestClient client;
#Test
void contextLoads() {
System.out.println(client.test(TestRequest.builder().foo("foo").build()));
}
}
This way your test will use the nested #Configuration instead of the automatically found #SpringBootConfiguration/#SpringBootApplication.

How to inject RequestScope bean in spring boot wicket application

In my Wicket page I have:
#SpringBean
protected J2EContext j2EContext;
In Configuration I have:
#Bean
#RequestScope
public J2EContext getWebContext() {
return new J2EContext(request, response, getSessionStore());
}
#Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
application starts OK but when I go to home page I got exception:
Caused by: java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given
at net.sf.cglib.proxy.Enhancer.emitConstructors(Enhancer.java:931)
at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:631)
at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:
329)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
when wicket want to inject J2EContext bean. I think this is because page is rendering before #RequestScope create this bean. Any idea how to fix this problem ?
to inject beans Wicket creates a proxy in two different ways:
If bean is an interface a standard java.lang.reflect.Proxy is created
If bean is a class cglib is used by default
Unfortunately cglib can not create proxy for classes without a default constructor. There is however a third way that can solve the problem. Just add objenesis as dependency to your project and Wicket will use it instead of cglib.

Hibernate 5 integration with Spring Boot 2

Am planning to create a spring boot (version 2) app with hibernate 5.3 , but am facing issues while integrating hibernate 5 .
Since its a spring boot app, the container will auto configure the datasource and JPA variant EntityManagerFactory and we can create Hibernate SessionFactory from this EntityManagerFactory using the unwrap() method.
So this is my code for the Hibernate config class
#Configuration
public class HibernateUtil {
#Autowired
private EntityManagerFactory entityMangerFact;
#Bean
public SessionFactory sessionFactory() {
return entityMangerFact.unwrap(SessionFactory.class);
}
}
But it is thowing BeanCurrentlyInCreationException .
But if i put the unwrap() in the service class method , it wont throw exceptions .but i think that not the right thing, since we will have more service methods, and we may need to call unwrap() on each service methods.
Error log:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sessionFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:339) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:215) ~[spring-beans-5.1.4.RELEASE.jar:5.1.4.RELEASE]
Why the unwrap() is failing in the configuration class ?
In spring-boot you have access EntityManagerFactory as you can check in this datasource configuration but you don't need to use EntityManager directly to interact with database, you can use spring-data-jpa
Can you try injecting it as SessionFactory bean dependency and not #Configuration bean?
#Configuration
public class HibernateUtil {
#Bean
public SessionFactory sessionFactory(EntityManagerFactory entityMangerFact) {
return entityMangerFact.unwrap(SessionFactory.class);
}
}

EJB abstract remote bean

I am developing Java6 web-app (.war) deployed onto glassfish-3 server. Part of my logic, concerned with DB connections etc. is part of another project - .ear deployed along with my app. It all worked well until instead of a simple managed beans I had to create another layer of abstraction to injected logic. Maybe the code will explain it best.
My web-app:
public class OtherClass {
#EJB(name = "IClass", mappedName = "A")
private IClass iClass;
}
}
.ear deployed app:
public abstract class AbClass {...}
#Stateless(name = "IClass", mappedName = "A")
public class A extends AbClass implements IClass {...}
#Stateless(name = "IClass", mappedName = "B")
public class B extends AbClass implements IClass {...}
Common imports (another project as a maven dependency):
#Remote
public interface IClass extends Serializable {...}
However that does not work and while trying to resolve #EJB throws:
Caused by: javax.naming.NameNotFoundException: A#.com.example.IClass not found
...
Caused by: java.lang.IllegalStateException: Exception attempting to inject Remote ejb-ref name=IClass,Remote 3.x interface =com.example.IClass,ejb-link=null,lookup=,mappedName=A,jndi-name=,refType=Session into class com.example.ItherClass: Lookup failed for 'java:comp/env/IClass' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming}
I am aware I could work around that problem for example by creating a Factory, but I was under the impression that that approach should work.

Categories

Resources