CDI -- #Inject not working among dependent projects - cdi

The basic architecture of my project (JBoss MSC version 1.0.2.GA-redhat-2) is like this
(VWebProj) --- >compile dependency ---> service project (QServiceProj)
(QServiceProj) ---->compile dependency ---> proxy project(VProxyProj)
(VProxyProj) ---->compile dependency ---> Manager project(VQManagerProj)
Manager project(VQManagerProj)
I have a manger class inside a Manager Project (VQManagerProj) which extends a class JDAO which in turn implements a interface VDAO
#Named("qManager")
#ApplicationScoped
public class QManager extends JDAO {...}
JDAO implements VDAO
Proxy Project (VProxyProj)
I have a proxy class inside Proxy Project (VProxyProj) which implements an interface VProxy and has the manager injected to it
#Named("vProxyImpl")
#ApplicationScoped
public class VProxyImpl implements VProxy {
#Inject #Named("qManager")
private VDao vdao;
}
Sevice Project (QServiceProj)
I have a service class inside Sevice Project (QServiceProj) which extends an abstract class
#Named
#ApplicationScoped
public class QService extends AbstractService {..}
Inside the abstract class I have the proxy injected
public abstract class AbstractService{
#Inject #Named("vProxyImpl")
private static VProxy proxy;
}
and using this proxy object the service class makes calls to the manager etc
Web Project (VWebProj)
Now I have a servlet inside the web Project (VWebProj) in which the service class is injected
#Inject
private QService qService;
The problem is that except qService none of the other injections work i.e inside QService proxy instance is null
however if I add all the injections directly in the servlet class like this
#Inject #Named("qManager")
private VDao vdao;
#Inject #Named("vProxyImpl")
private static VProxy proxy;
They are all initialized but if I go via QService they are null
I have put beans.xml in all the projects,
Thanking in advance
Charlie

As far as I know Injector can only inject objects into instances and their fields - You are trying to "inject" dependencies into static fields.
I suggest using #Singleton annotation instead - create separate instance that would hold all your current static references, and inject that singletons into Your instances instead.
#Singleton
class ProxyService {
#Inject #Named("vProxyImpl")
private VProxy proxy;
public VProxy getProxy() {
return proxy;
}
}
public abstract class AbstractService{
#Inject
private ProxyService proxyService;
}
Alternatively You can consider making VProxy singleton - I seems that what You want to obtain is just one instance of Proxy in a whole application. You need to decide yourself what is that best approach here.

Related

OSGI services not loading in Mockito unit tests

I have several service classes that are not loading in Mockito for unit testing. The services are being loaded in classes and Sling models using the #Reference and #Inject annotations.
The case is that I have several services and Sling models that are loading other services using the #Inject or #Reference annotations.
public class MyModel{
#Inject
SomeService service;
}
public class MyService{
#Reference
SomeOtherService service;
}
Then when I have a unit test mock the service, the injected services are not loaded. How do I get them loaded into the mock context so that they load are tested as well?
I found that I need to create an instance of the SomeService object and then use the AemContext.registerInjectActivateService() method or the SlingContext.registerInjectActivateService() method to inject them into the context so they are available when the classes being tested load.
You can simply use the mockito #InjectMocks annotation on your class under test and provide the services to be injected as #Mock.

Micronaut and PowerMock

I am trying to use PowerMock(as i have some legacy static methods) in a micronaut based application. But when I try to run the application all micronaut beans are getting injected as null (and the underlying mocks as well)
#RunWith(PowerMockRunner.class)
#PrepareForTest({MyStaticClass.class, ClassToBeTested.class})
public class TestClass {
#InjectMocks
private ClassToBeTested obj1;
#Mock
private LegacyStaticClass1 obj2;
#Mock
private MicronautBasedBean obj2;
#Before
public void setup(){
MockitoAnnotations.initMocks(this);
MockitoAnnotations.initMocks(this);
}
Is there a #PowerMockRunnerDelegate or PorwerMock runner from micronaut (like SpringRunner)
also my #Before doesntt get called to inject mocks in this case
I tried using
#MicronautTest on the TestClass but then PowerMock is not able to mock static class.
Is there a #PowerMockRunnerDelegate or PorwerMock runner from
micronaut?
Not currently, no. Feel free to file a feature request at https://github.com/micronaut-projects/micronaut-test/issues. We welcome pull requests too of course.

Use SAP Cloud SDK to integrate with a custom backend service (oData) based on VDM Generator

I followed Alexander Duemont's blog, trying to implement a Java Spring Boot application that consumes Cloud Foundry Destination. The Destination has a custom OData V2 behind it, coming from an On-Premise ERP system. For local dev, when I perform the Maven build, the Integration-Tests module registers failure due to dependency injection
This is part of my Controller
#RestController
#RequestMapping("/resources")
public class ClassificationsController {
private static final Logger logger = CloudLoggerFactory.getLogger(ClassificationsController.class);
private final ClassificationService service;
public ClassificationsController(#Nonnull final ClassificationService service) {
this.service = service;
}
…..
}
The #Nonnull final ClassificationService Service causes org.springframework.beans.factory.UnsatisfiedDependencyException
I cannot use Spring stereotype annotations on generated Service classes (Fluent) to create Beans!
This question is more likely related to Spring Boot configuration.
I'm assuming ClassificationService is an interface and the implementing class exists in the same package.
Please make sure...
... to add the implementing class of ClassificationService to your component scan / test runtime. Feel free to share the integration test code to setup the test environment. Maybe the additional class reference is missing.
... to correctly annotate the respective Application class of your Spring Boot project. For example, assuming your ClassificationService resides in org.example.services.classification, while the rest of your application uses org.example.app. Your basic Application class would look like this, when following the Cloud SDK guide:
#SpringBootApplication
#ComponentScan({"com.sap.cloud.sdk", "org.example.services.classification", "org.example.app"})
#ServletComponentScan({"com.sap.cloud.sdk", "org.example.app"})
public class Application extends SpringBootServletInitializer
{
#Override
protected SpringApplicationBuilder configure( final SpringApplicationBuilder application )
{
return application.sources(Application.class);
}
public static void main( final String[] args )
{
SpringApplication.run(Application.class, args);
}
}
... to annotate the implementing class of ClassificationService with javax.inject.Named. In case you have multiple implementations of the same interface, make sure to give the not-used class a custom (unique) value for the #Named annotation.
... to look for exceptions (Class not found) in the application log during startup.

JSF application backend architecture with JPA and CDI

I'm working on a JSF application with JPA and CDI; I use the following backend architecture:
Controllers (CDI annotation for JSF process)
Services (CDI annotations to be injected into Controllers and other Services)
DAOs (handled with EntityManager)
My question is, how should exactly be EntityManager and transactions be handled?
For example transactions (I don't use EJB or Deltaspike, so no declarative transactions available) should be managed by the Service layer (am I right?), but each data-releated other operation should be handled by the DAOs. So where should EntityManager be injected?
Also, should EntityManager be request (or session or method) scoped?
Thanks,
krisy
I would use service layer to manage a business logic and data access layer to manage object-relational model. As a consequence of the above, entity manager and transactions should be part of DAO. It's important to keep transactions as short as possible.
The decision which type of scope to choose is not so obvious as it depends on the nature of your bean/application. An example usage followed by this presentation, slide #15:
#RequestScoped: DTO/Models, JSF backing beans
#ConversationScoped: multi-step workflow, Shopping cart
#SessionScoped: User login credentials
#ApplicationScoped: Data shared by entire app, Cache
As you can see a scope of a given bean and the related entity manager is specific for the problem it concerns. If a given bean is request scoped its state is preserved for a single HTTP request in the same HTTP session. For a session scoped bean the state is maintained through HTTP session. An example approach may look somehow like the following (pseudocode):
#SessionScoped // conversation, application scoped as well
public class ServiceImpl implements Service {
#Inject
private Dao dao;
public void createSomething(SomeDto dto) {
// dto -> entity transformation
dao.create(entity);
}
public SomeDto getSomething(int id) {
SomeEntity entity = em.findById(id);
// entity -> dto transformation
return dto;
}
}
#RequestScoped
#Transactional
public class DaoImpl implements Dao {
#Inject
private EntityManager em; //creating em is cheap
// TxType.REQUIRED by default
public void create(SomeEntity entity) {
em.persist(entity);
}
#Transactional(TxType.NOT_SUPPORTED)
public SomeEntity findById(int id) {
return em.find(SomeEntity.class, id);
}
}

What is the most concise way to get an injected bean for a springboot managed class?

I have a simple application that injects another component
#ComponentScan
#EnableAutoConfiguration
#Configuration
class Application {
static void main(String[] args) {
SpringApplication.run(Application, args)
}
#Bean
AuthorizationServerTokenServices tokenServices() {
return MY THING HERE
}
}
I'd like a quick/minimal way to new this up and grab the item springboot wires up (for tokenServices in this example). I'm trying to get at this to verify some configuration/settings/etc using TestNG
I should also say that I"m not using any xml to configure this (using gradle/groovy/springboot)
You can easily introduce conditional bean with the help of Spring profiles.
In your case the code would look like:
#Configuration
#Profile("tokenService")
public TestTokenServiceConfig {
#Primary
#Bean
AuthorizationServerTokenServices tokenServices() {
//implementation
}
}
The custom implementation you supply in this class will only be used by Spring in case the profile tokenService is active. The use of #Primary is needed in order to make Spring use the specified bean instead of any others present in the application context.
Also note that since you are going to be using the custom service in a test environment, you could easily mock the implementation using Mockito (or whatever other mocking framework you prefer)
And the actual integration test would be something like:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#ActiveProfiles("tokenService")
class YourIntegrationTest {
#Autowired
AuthorizationServerTokenServices tokenServices;
//test
}

Resources