Currently I have the following setup (to keep it small I did not post all annotations):
public class MessageRestService {
private MessageService messageService;
MessageRestService(MessageService messageService) {
this.messageService = messageService;
}
#GetMapping
public Response getAllMessages() {
return messageService.getAllMessages();
}
}
public interface MessageService {
String getAllMessages();
}
public class MessageServiceImpl implements MessageService {
#Override
public String getAllMessages() {
...
return messageDao.getAllMessages();
}
}
Now I'm trying to add a decorator class to this implementation, where before the call additional things can be done (e.g. access check or logging,...).
Therefore I tried to create a decorator class which can do f.ex. logging, before the actual implementation gets called.
#Singleton
public class MessageDecorator implements MessageService {
#Inject
private final MessageService messageService;
#Override
public String getAllMessages() {
// here we can log
return messageService.getAllMessages();
}
}
The project is compiling without problems, but calling the getAllMessages() method, the decorator does not get called, the process (works) as before, but without logging anything.
I'm honestly stuck, I have seen once a working example of this, but I do not remember exactly anymore what was different to my approach or where I did a mistake / forgot to change something.
Related
I am working on an application with a WebSocket and want to save the clients id and session to a manager but have difficulties to understand how to do this correct when I also want to be able to reach this from another class with autowire.
public class Client {
private String id;
private Session session;
private MessageHandler handler;
Client(String id, Session session, MessageHandler handler) {
this.id = id;
this.session = session;
this.handler = handler;
}
}
public class ClientsManager {
private Set<Client> clientSet = new CopyOnWriteArraySet<>();
public Set<Client> getClients() {
return this.clientSet;
}
public void addClient(Client client) {
this.clientSet.add(client);
}
public void removeClient(Client client) {
clientSet.remove(client);
}
}
public class WebsocketServerEndpoint {
public static final ClientsManager manageClients = new ClientsManager();
#OnOpen
public void onOpen(Session session, #PathParam("connectId") String connectId) throws IOException, EncodeException {
MessageHandler messageHandler = new MessageHandler();
Client client = new Client(connectId, session, messageHandler);
this.client = client;
manageClients.addClient(client);
}
....
....
....
....
}
From another class:
public class DoSomething {
#Autowired
WebsocketServerEndpoint serverEndpoint;
public String doSomething() {
int numberOfClients = serverEndpoint.getClients().size()
return numberOfClients;
}
}
As I understand. This is not correct and you should not autowire static fields and so.
I can see when I debug that serverEndpoint: null in my DoSomething class but I get 1 connected client if I have one connected and so on.
When I do like this I will get the right number of clients in DoSomething class.
Have I just misunderstood this and it works as I have done?
or how should I do instead?
Is their a better way to write my Client and ClientsManager classes?
What I have read that if I would like to "Autowire" anyway there is two possible ways.
Using Constructor #Autowired For Static Field
Using #PostConstruct to set the value to Static Field
But how does this work when I would like to instantiate "public static final ClientsManager manageClients = new ClientsManager();"
Sorry for my stupid question but I feel I do not fully understand this.
If you would like to understand more about this topic search for Spring Dependency injection, but I write a short summary.
To be able to #Autowire a component you have to create a #Bean or #Service or #Component.
Creating beands first create a Configuration class, and a Beand or Beans inside.
#Configuration
public class Configuration {
#Value("${configuration.property.name}")
String username;
#Bean
public WebsocketServerEndpoint ebsocketServerEndpoint () {
return new WebsocketServerEndpoint();
}
}
#Value is not necessaty just good to mention with this annotation you can get a property name from spring application.properties file.
After this point you have created a #Bean instance of your class it is registered as a singleton class. You can get this one copy class from anywhere in your application you just have to, autowire it.
Or user construcor based dependency injection. ( #Autowired is not prefered).
Dont create beans just add #Component annotation to your class that you want to Autowire but I show a constructor injection.
#Component
public class WebsocketServerEndpoint {
public String test(){
return "test";
}
}
#RestController
public class DoSomething {
private final WebsocketServerEndpoint websocketHandler;
public DoSomething(WebsocketServerEndpoint websocketHandler) {
this.websocketHandler = websocketHandler;
}
#GetMapping(value = "/test")
public String test() {
return websocketHandler.test();
}
}
You can even test this endpoint with a curl GET request. curl http://localhost:8080/test
I'm working on an application that uses Spring Boot. In it, an interface is used in a way that I don't understand.
I've stripped down the code to the only parts that I think are relevant to the question.
A controller object is created.
It is told to process some stuff.
The controller tells an interface processor to do the work.
There is a processor that implements the interface processor.
It was my understanding that when using an interface you'd do something like: IProcessor iProcessor = new Processor();
In other words, assigning the interface an implementation. But in this sample program it seems the processor implementation is implicitly assigned, not in the code as far as I can tell. I'm trying to figure out if this is some Spring wizardry or if I'm just understanding interfaces wrong. There are four files that I have put in order of application flow.
#Component
public class DoStuff {
private ProcessorController PROCESSOR_CONTROLLER;
private OtherLayer OTHER_LAYER;
#Autowired
public DoStuff(ProcessorController processorController, OtherLayer otherLayer) {
this.PROCESSOR_CONTROLLER = processorController;
this.OTHER_LAYER = otherLayer;
}
public void execute() {
List<String> stuffToProcess = OTHER_LAYER.getStuffToProcess();
PsROCESSOR_CONTROLLER.process(stuffToProcess);
}
}
#Component
public class ProcessorController {
private final IProcessor IPROCESSOR;
#Autowired
public ProcessorController(IProcessor iProcessor) {
this.IPROCESSOR = iProcessor;
}
public void process(List<String> stuffToProcess) {
stuffToProcess.forEach(t -> IPROCESSOR.process(t))
}
}
public interface IProcessor {
void process(String stuff);
}
#Component
public class Processor implements IProcessor {
#Override
public void process(String stuff) {
System.out.println(stuff);
}
}
If the ProcessorController class contained something like this:
So part of the ProcessorController class would look like this instead:
private final IProcessor IPROCESSOR;
#Autowired
public ProcessorController(Processor Processor) {
this.IPROCESSOR = processor;
}
I think it would make sense since we've linked the interface with its implementation. But it isn't that way. So what is going on here?
Your understanding is correct
IProcessor iProcessor = new Processor();
The above way is correct way to assigning the implementation to Interface reference variable.This phenomena is known as loose coupling .Because if the method parameter type is of interface then it can be bind with multiple implementation based on requirement .
For Example we have
interface Test and Test1 and Test2 are its implementation classes
Then void method(Test test)
so now this method can bind with both Test1 and Test2 like method(Test1 obj) and method(Test2 obj)
But your controller is tightly coupled here not loosely coupled.Because Your constructor call is bind with Implementation class reference not interface.And if your project need tight coupling then there is no use to create class refrence of interface type rather you can create private final Processor PROCESSOR; instead of below code
private final IProcessor IPROCESSOR;
#Autowired
public ProcessorController(Processor Processor) {
this.IPROCESSOR = processor;
}
It should be like
#Autowired
private final IProcessor IPROCESSOR;
or
private final IProcessor IPROCESSOR;
#Autowired
public ProcessorController(IProcessor Processor) {
this.IPROCESSOR = processor;
}
I have a class with 2 static nested classes that do the same operation on 2 different generic types.
I exposed the 2 classes as beans and added #Autowired for the constructors as I usually do.
Here is the basic setup
abstract class <T> Parent implements MyInterface<T> {
private final Service service;
Parent(Service service){ this.service = service; }
#Override public final void doInterfaceThing(T thing){
T correctedT = map(thing);
service.doTheThing(correctedT);
}
protected abstract T map(T t);
#Service
public static class ImplA extends Parent<A> {
#Autowired ImplA (Service service){ super(service); }
A map(A a){ //map a }
}
#Service
public static class ImplB extends Parent<B> {
#Autowired ImplB (Service service){ super(service); }
B map(B b){ //map b }
}
}
And in another class I have
#Service
public class Doer {
private final List<MyInterface<A>> aImpls;
#Autowired public Doer(List<MyInterface<A>> aImpls){ this.aImpls = aImpls; }
public void doImportantThingWithA(A a){
aImpls.get(0).doInterfaceThing(a);
}
}
When I run the app, everything appears to be injected correctly and when I put a breakpoint in the ImplA and ImplB constructors, I have a not-null value for "service". I also have an ImplA bean in the aImpls list in Doer.
When I call doImportantThingWithA(a) however, "service" is null inside ImplA and I obviously die.
I'm not sure how this is possible because:
I see a nonnull value in my constructors for service which is a final field.
If spring is injecting ImplA and ImplB into another class, it should already have either injected a Service into ImplA or ImplB, or thrown an exception on bean initialization. I have nothing set to lazily load and all bean dependencies are required.
The reason for the nested classes is because the only thing that changes between the 2 implementations is the map() function. Trying to avoid extra classes for 1 line of varying code.
More info:
When I add a breakpoint in Parent.doInterfaceThing(), if I add a watch on "service" I get null as the value. If I add a getService() method, and then call getService() instead of referring directly to this.service, I get the correct bean for service. I don't know the implications of this but something seems weird with the proxying.
It looks like what is causing the issue is Parent.doInterfaceThing();
If I remove final from the method signature, "service" field is correctly populated and the code works as expected.
I don't understand at all why changing a method signature affects the injected value of final fields in my class... but it works now.
What I meant with my "use mappers" comment was something like this:
class MyInterfaceImpl implements MyInterface {
#Autowired
private final Service service;
#Override public final <T> void doInterfaceThing(T thing, UnaryOperator<T> mapper){
T correctedT = mapper.apply(thing);
service.doTheThing(correctedT);
}
// new interface to allow autowiring despite type erasure
public interface MapperA extends UnaryOperator<A> {
public A map(A toMap);
default A apply(A a){ map(a); }
}
#Component
static class AMapper implements MapperA {
public A map(A a) { // ... }
}
public interface MapperB extends UnaryOperator<B> {
public B map(B toMap);
default B apply(B b){ map(b); }
}
#Component
static class BMapper implements MapperB {
public B map(B a) { // ... }
}
}
This does have a few more lines than the original, but not much; however, you do have a better Separation of Concern. I do wonder how autowiring works in your code with the generics, it does look as if that might cause problems.
Your client would look like this:
#Service
public class Doer {
private final List<MapperA> aMappers;
private final MyInterface myInterface;
#Autowired public Doer(MyInterface if, List<MapperA> mappers){
this.myInterface = if;
this.aImpls = mappers; }
public void doImportantThingWithA(A a){
aMappers.stream().map(m -> m.map(a)).forEach(myInterface::doInterfaceThing);
}
}
I have this Restful service:
#Service
public class MyRESTServiceImpl implements MyRESTService {
#Inject
private Helper helper;
public MyRESTServiceImpl() {
}
#Override
public List<Something> getThings() {
return helper.getThings(); // NPE here!
}
}
The problem here is that when getThings is accessed through /api/getThings, although the method is invoked the helper is not injected. Whereas on the other parts of the app it injected properly. I am missing some annotation for this MyRESTServiceImpl?
Let's pretend that I have an interface called IValidator that looks like the following:
public interface IValidator {
/**
* Returns true if the specified strings are valid.
*/
public boolean validate(List<String> someStrings);
}
Now let's say that I have two implementations of IValidator:
public class StrictValidator implements IValidator {
public boolean validate(List<String> someStrings) {
//some strict validation code
return false;
}
}
public class LaissezFaireValidator implements IValidator {
public boolean validate(List<String> someStrings) {
//some easy-going validation code
return true;
}
}
Now let's add a servlet that uses an injected instance of IValidator:
#Service
#At("/rest")
public class MyServlet extends AbstractServlet {
private final IValidator validator;
#Inject
public MyServlet(final IValidator validator) {
this.validator = validator;
}
#Post
#At("/validate")
#LaissezFaire
public Reply<?> validate(Request request) {
//get the strings to validate out of the request object
List<String> strings = (List<String>) restUtil.parseRequest(request, List.class);
//validate the request
if (!this.validator.validate(strings)) {
return Reply.saying().status(409);
} else {
return Reply.saying().noContent();
}
}
}
Of course we'll also need to bind IValidator to StrictValidator in a module:
public class ValidatorModule implements Module {
#Override
protected void configure() {
bind(IValiator.class).to(StrictValidator.class);
}
}
But what happens if I want to conditionally bind IValidator to StrictValidator in one case, but instead bind it to LaissezFaireValidator in some other case?
Did you notice the #LaissezFaire annotation on MyServlet.validate above? That's an interceptor that looks like this:
#BindingAnnotation
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface LaissezFaire { }
public class LaissezFaireInterceptor implements MethodInterceptor {
private boolean debug;
private IValidator validator;
#Inject
public void setDebug(#Named("debug.enabled") boolean debugEnabled) {
this.debug = debugEnabled;
}
#Inject
public void setValidator(final IValidator validator) {
this.validator = validator;
}
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (debug) {
if (!this.validator.validate(strings)) {
return Reply.saying().status(409);
} else {
return Reply.saying().noContent();
}
} else {
return invocation.proceed();
}
}
}
And once again we need some bindings to set up the interceptor:
public class InterceptorModule implements Module {
#Override
protected void configure() {
final MethodInterceptor lfInterceptor = new LaissezFaireInterceptor();
requestInjection(lfInterceptor);
bindInterceptor(Matchers.subclassesOf(AbstractServlet.class), Matchers.AnnotatedWith(LaissezFaire.class), lfInterceptor);
}
}
According to the ValidatorModule, the LaissezFaireInterceptor class will get an instance of StrictValidator when InterceptorModule calls requestInjection(lfInterceptor);.
Instead, I'd like MyServlet to get an instance of StrictValidator and LaissezFaireInterceptor to get an instance of LaissezFaireValidator.
According to the Google Guice docs, I could use a named annotation when I request injection. The constructor of MyServlet would be modified to look like the following:
#Inject
public MyServlet(#Named("strict") final IValidator validator) {
this.validator = validator;
}
and the setValidator method of LaissezFaireInterceptor would be modified to look like the following:
#Inject
public void setValidator(#Named("laissezfaire") final IValidator validator) {
this.validator = validator;
}
and finally ValidatorModule would be modified to look like the following:
public class ValidatorModule implements Module {
#Override
protected void configure() {
bind(IValiator.class).annotatedWith(Names.named("strict")).to(StrictValidator.class);
bind(IValidator.class).annotatedWith(Names.named("laissezfaire")).to(LaissezFaireValidator.class);
}
}
This is all well and good except that the docs specifically say to avoid this approach because the string names can't be checked by the compiler. In addition, it means that I have to add an #Named annotation to every place in the code that requests an IValidator by injection, or else the binding will fail.
I had really hoped that Provider Bindings could solve this problem for me, but they don't appear to know anything about the context in which the binding is being made. Since they don't know the type of the class that is requesting the binding, I can't choose which type of IValidator to return from the get() method.
Is there a better way to approach this problem?
While Condit supplied some excellent suggestions, we opted to solve this problem with a more straightforward solution.
As above, we created the IValidator interface, as well as the StrictValidator and LaissezFaireValidator classes. We used the ValidatorModule to bind IValidator to StrictValidator in the default case. As a reminder, it looks like this:
public class ValidatorModule implements Module {
#Override
protected void configure() {
//in the default case, inject an instance of StrictValidator
bind(IValiator.class).to(StrictValidator.class);
}
}
In the vast majority of cases, StrictValidator is the required implementation, as the LaissezFaireInterceptor is a cheat that is used for testing.
Wherever we wanted a StrictValidator (like we do in MyServlet), we injected an instance of IValidator:
public class MyServlet extends AbstractServlet {
private final IValidator validator;
#Inject
public MyServlet(final IValidator validator) {
this.validator = validator;
}
//... there's more code here (look above) ...
}
And wherever we wanted an instance of LaissezFaireValidator, we asked for its concrete implementation to be injected in place of IValidator:
public class LaissezFaireInterceptor implements MethodInterceptor {
private final IValidator validator;
//... a bunch of other code goes here (see above) ...
#Inject
public void setValidator(final LaissezFaireValidator validator) {
this.validator = validator;
}
//... and a bunch more code goes here (again, see above) ...
}
In this way, we were able to conditionally inject the required implementation based on the context of the injection without introducing any extra annotations or factories.
Sure, it's not as Guicy as it could be, but it works.