Bean interface and Bean implementation in different projects - java

Is it possible to have a bean interface in a project and the implementation of that bean in another project that includes the previous project as a dependency?
I have the following interface:
package com.proj1.util;
import .....;
public interface Notification {
addNotification();
addError();
}
In the same project (i.e. Proj1) I have also the following class:
package com.proj1.util.exception;
import .....;
public class ExceptionHandler extends RuntimeException ... {
private String errorMessage;
#Override
public void handle() {
Util.getBeanInstance(Notification.class).addError(errorMessage);
}
}
Now in the second project I have the actual implementation of Notification that is as follows:
package com.proj2.beans;
#Named
#ConversationScoped
public class NotificationBean implements Notification, Serializable {
private static final long serialVersionUID = 1L;
...
}
This situation leads to an exception in Tomcat with the message "WebBeans context with scope type annotation #ConversationScoped does not exist within current thread"
My proposal was to add a Factory that produces my NotificationBean but it doesn't seem to change much.
package com.proj2.beans.cdi;
import javax.enterprise.inject.New;
import javax.enterprise.inject.Produces;
import com.proj1.util.Notification;
public class NotificationBeanFactory {
#Produces
public Notification create(#New NotificationBean notificationBean) {
return notificationBean;
}
}
The question is how can I use a bean in a project in which I have only it's interface while the bean implementation is in another project. Is it possible?

The exception suggests there is no running conversation so I would start by determining when do you attempt to use #ConversationScoped bean and from which class.
Your code pieces indicate that ExceptionHandler class calls a magical formula which we do not know anything else about:
Util.getBeanInstance(Notification.class).add(...);
Trying to use this when there is no active conversation might lead to the exception you see. Therefore you could #Inject ExceptionHandler into NotificationBean so that you only ever use it while there is active conversation.
As for the Weld question regarding interface and impl in different projects; it is possible. in your proj2 Weld will simply identify a bean NotificationBean and amongst it's types there will also be Notification hence you can then #Inject Notification.
It might not work the other way round though - in proj1 you cannot #Inject Notification because proj1 itself does not have any bean which would implement that interface.

Related

Why I should declare bean on constructor?

I have a class ServiceA on project-a:
public class ServiceA {
private ModelA modelA;
public ServiceA(ModelA modelA) {
this.modelA = modelA;
}
}
modelA from other local library (external library). modelA have #Component annotation
when I run this code, cannot found error bean on ModelA. I solve with add #Bean for ModelA on project-a.
Why I should add bean? because the ModelA on external library? Any reference link for I can understand for this case? I want understand for this code. Thank you
The first comment is the most likely answer to your issue;
specifically,
the component scanning that is configured in your project does not include the package that contains the modelA class.

SpringBoot #Autowire why does this example work?

I have created this class:
import org.springframework.stereotype.Component;
...
#Component("notTheNameTestMe") //shouldnt this only work with testMe ?
public class TestMe {
public void showMsg() {
System.out.println("Autowiring works");
}
}
And I'm using it this way in a second class (or better: controller):
import com.example.TestMe; //shouldnt this be not necessary with autowire? But getting error else...
...
#Autowired
private TestMe testMe;
...
this.testMe.showMsg();
But this works perfectly (so maybe Im not really using autowire here?), it even works if I rename the whole TestMe class to TestMeSomething (if I adjust the import in the second class)
I dont really understand what #Autowired does. I thought it just scans for SpringBoot Components (which are named by the string in #Component() and when it finds a match it Injects the dependancy. But in my example the match is impossible and I still can see the message "Autowiring works" in the console. This shouldnt be like this if I would really use autowire here or? What am I understanding in a wrong way? What is the difference to using new TestMe() then? I have the dependancy already with the import or? So not a real dependancy injection, or?
Spring is not operating on the name in the #Component annotation. Rather it's using the name of the class. It's simply finding a class named TestMe because that's the type of the variable you've annotated with #Autowired.

Autowiring a subclass but using parent class as reference

Say I have the below class hierarchy:
// Not a component
public class Parent {
}
// See update; this resides in another application context
#Component
public class Child extends Parent {
}
I would like to autowire the Child bean using constructor injection.
#Component
public class Test {
private final Parent parent;
public Test(#Qualifier("child") Parent parent) {
this.parent = parent;
}
}
But Spring is not letting me do this and I get an exception thrown saying:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.foo.Parent' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Qualifier(value=child)}
Is there a way to make this work?
Update
OK, first of all, there is no way you could have come up with an answer to this problem as I made a mistake and did not analyse the situation properly before asking the question.
So what was happening was that the "child" in my case resided in a different application context, which happened to be a bean in the main application context. Because of this reason, what would have been a standard Spring practice, would not have worked for me.
I will post my answer as the solution to this updated scenario.
I think you kinda imitate situation when you try to autowire some class from any outer library. You have to get beans through xml or java config. I think this should work and you should to remove component from Child.
But anyway there should be big reasons to do that. Simple spring autorwiring is more concise and traditional
package com.bssys.ufap.report.springconfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class MyConfig {
#Bean
public Parent getChild() {
return new Child();
}
}
So the solution involved simply looking up the bean from the other application context as follows:
#Component
public class Test {
private final Parent parent;
public Test(ApplicationContext applicationContext) {
this.parent = applicationContext.getBean("anotherContext", ApplicationContext.class).getBean("child", Parent.class);
}
}

#Path Annotation requirements?

I'm new to specifying resource routes in Java, and I'm having issues specifying the route. So far I have one Class which simply extends Application, and one class that reacts to input. What are the routing requirements for these classes? My code below does not work and im trying to figure out why. I've tried to find sources for these, but haven't had much luck.
Can I just use a / for the ApplicationPath? All this class does is extend Application so it can find routes.
Example:
package com.sentiment360.helloworld;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
/**
* JAXActivator is an arbitrary name, what is important is that javax.ws.rs.core.Application is extended
* and the #ApplicationPath annotation is used with a "rest" path. Without this the rest routes linked to
* from index.html would not be found.
*/
#ApplicationPath("/")
public class JAXActivator extends Application {
}
Does each class need to have a declared #Path (or can they all be #Stateless)?
#Path("/helloservice")
public class HelloService {
private static Logger _logger;
public HelloService(){
_logger = Logger.getLogger(HelloService.class.getName());
}
private Connection conn() throws SQLException {...}
}
The short version for #1 is yes.
BUT: behavior is implementation dependent. See https://stackoverflow.com/a/16747253/1063501 for a thorough explanation.
As for #2, yes, you generally need to specify a #Path for every endpoint you want. The fact that it is #Stateless is irrelevant as you'll need a way to address it.

Play Framework Dependency Injection

I've been looking all over Google to find some useful information on how to use Guice/Spring DI in Play Framework 2.1
What I want to do is to Inject several Services in some DAO's and vice versa.
Just need some clarification on this - With play 2.1, do you have to use an # annotation within the routes file for DI?
I've looked at this guide here - https://github.com/playframework/Play20/blob/master/documentation/manual/javaGuide/main/inject/JavaInjection.md
and applied the following steps creating a Global class in app and adding the GUICE dependencies in Build.scala but keep on getting a null pointer exception when invoking on the injected object.
Has anyone been able to get DI working in Play 2.1 using Guice? I've seen examples across the internet but they all seem to be using DI within the controller.
I noticed you are using Java. Here is how I got it to work for injecting into a controller.
First, I created the following 4 classes :
MyController:
package controllers;
import play.mvc.*;
import javax.inject.Inject;
public class MyController extends Controller {
#Inject
private MyInterface myInterface;
public Result someActionMethodThatUsesMyInterface(){
return ok(myInterface.foo());
}
}
MyInterface:
package models;
public interface MyInterface {
String foo();
}
MyImplementation2Inject:
package models;
public class MyImplementation2Inject implements MyInterface {
public String foo() {
return "Hi mom!";
}
}
MyComponentModule:
package modules;
import com.google.inject.AbstractModule;
import models.MyInterface;
import models.MyImplementation2Inject;
public class ComponentModule extends AbstractModule {
#Override
protected void configure() {
bind(MyInterface.class).
to(MyImplementation2Inject.class);
}
}
Now the final part, that took me a silly long time to figure out, was to register the module. You do this by adding the following line to the end of the application.conf file, which is located in the conf directory:
play.modules.enabled += "modules.MyComponentModule"
I hope this was helpful to you. :)
I use cake pattern and my own version of Global overriding getControllerInstance
https://github.com/benjaminparker/play-inject
Cheers
Ben
Sorry, this is a late response, but here's our example
https://github.com/typesafehub/play-guice
Have you tried using some different approach to DI than Guice?
We also tried implementing a project with Guice or Spring but ended in registering our dependencies in objects that implement trait such as:
trait Registry {
def userDao: UserDao
...
}
object Registry {
var current: Registry = _
}
object Environnment {
object Dev extends Registry {
val userDao = ...
//implement your environment for develpment here
}
object Test extends Registry {
val userDao = ...
//implement your ennviroment for tests here e.g. with mock objects
}
}
Another good approach wich might fit for you is the cake pattern (just google for it).

Categories

Resources