How to change dependency in already deployed application. So when application starts it send notification through email, but at some moment we should be able to change to send notification through sms.
How to do that in Spring Boot?
thats a work for a strategy pattern, it does not have anything to do with spring itself
You should have 2 strategies one for email and one for sms, in each strategy you will autowired the needed bean.
check this link for strategy implementation
https://www.tutorialspoint.com/design_pattern/strategy_pattern.htm
You can define a property in a Singleton bean? let's call it notificationMethod and assign by default EMAIL. (the property could be enum or string or int no matter).
You need a controller method to change the property.
#Autowired
private MyNotificationMethodHolderService service;
#RequestMapping(value = "/changeNotificationMethod")
#ResponseBody
public String change(#RequestParam("methodName") String methodName) {
service.setNotificationMethod (methodName);
}
Your notification service checks the property and sends notification according to the value (Strategy pattern according to comments).
If you need to change method you invoke
<HOST>:<PORT>/context/changeNotificationMethod?methodName=SMS
Related
I'm working on a websocket application where I'm trying to have one websocket that feeds information in, and then outputs to subscribers to the endpoint. I've figure that out, but I'm wondering if there is a way to see what subscribers are subscribed and to what path?
Here is a code sample of what I'm working on.
#Autowired
private SimpMessagingTemplate template;
#MessageMapping("/{companyId}/{departmentId}")
#SendTo("/{companyId}/{departmentId}")
public void companyInformation(#DestinationVariable String companyId, #DestinationVariable String departmentId, CompanyMessage companyMessage){
String destination = "/" + companyId + "/" + departmentId;
template.convertAndSend(
destination, processCompanyMessage(companyMessage, departmentId));
}
The idea is that the information poster sends companyMessage object to the #MessageMapping endpoint, the companyId and departmentId are retrieved from this mapping.
This message is then processed based on what the departmentId is and is posted to every department that has an active subscriber to the #SendTo path.
e.g.
There are 3 websocket subscribers,
/smallCompany/booking, /smallCompany/sales, /smallCompany/inventory.
#MessageMapping gets a message from /smallCompany/sales. The method processes the message based on the departmentId and posts to EVERY subscriber with the same /{companyId}, even if the /{departmentId} differs.
Any ideas if this is possible, and if not, any ideas to push me in the right direction would be great.
I know it's too late to answer! but I saw this question now!
So, to guide others that will see this question, I should say:
You have several solutions:
1- SimpUserRegistry:
#Autowired private SimpUserRegistry simpUserRegistry;
public Set<SimpUser> getUsers() {
return simpUserRegistry.getUsers();
}
Check this link:
Is there a Spring WebSocketSession repository?
2- Global list:
You've certainly configured the web-socket in spring boot, so, probably you have a derived class from WebSocketMessageBrokerConfigurer, with override configureClientInboundChannel to call setInterceptors...
You should implement custom interceptor derived from ChannelInterceptorAdapter and override preSend to access MessageHeaderAccessor.getAccessor(...).command
These commands defined in StompCommand (CONNECT, DISCONNECT, SUBSCRIBE, UNSUBSCRIBE,...)
By checking accessor.command with StompCommand.SUBSCRIBE/UNSUBSCRIBE you can create and sync a global static list of subscribers, and use it everywhere you need.
3- Other solution:
Check this link:
how to capture subscribe event in my webSocket server with Spring 4
If I use Spring, which of these two methods is more correct.
Can I use the new() operator even if I use dipendency injection?.Can I mix both?
I would like to have some clarification on these concepts.
Thanks
First method:
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(new User());
return "index";
}
Second Method:
#Autowired
User user;
#RequestMapping(method=RequestMethod.GET)
public String create(Model model){
model.addAttribute(user);
return "index";
}
By using dependency injection does not mean that the use of new operator is automatically prohibited throughout your code. It's just different approaches applied to different requirements.
A web application in spring is composed of a number of collaborating beans that are instantiated by the framework and (unless overriding the default scope) are singletons. This means that they must not preserve any state since they are shared across all requests (threads). In other words if you autowire the User object (or any other model attribute), it is created on application context initialization and the same instance is given to any user request. This also means that if a request modifies the object, other requests will see the modification as well. Needless to say this is erroneous behavior in multithreaded applications because your User object (or other model attribute) belongs to the request, so it must have the very narrow scope of a method invocation, or session at most.
You can also have spring create beans with different scopes for you, but for a simple scenario of a model attribute initialization, the new operator is sufficient. See the following documentation if interested in bean scopes : Bean scopes
So in your use case, the second method is totally wrong.
But you can also delegate the creation of your model attributes to spring if they are used as command objects (i.e. if you want to bind request parameters to them). Just add it in the method signature (with or without the modelattribute annotation).
So you may also write the above code as
#RequestMapping(method=RequestMethod.GET)
public String create(#ModelAttribute User user){
return "index";
}
see also : Supported method argument types
If you want your beans to be "managed" by Spring (for e.g. to use with Dependency Injection or PropertySources or any other Spring-related functionality), then you do NOT create new objects on your own. You declare them (via XML or JavaConfig) and let Spring create and manage them.
If the beans don't need to be "managed" by Spring, you can create a new instance using new operator.
In your case, is this particular object - User - used anywhere else in code? Is it being injected into any other Spring bean? Or is any other Spring bean being injected in User? How about any other Spring-based functionality?
If the answer to all these questions is "No", then you can use the first method (create a new object and return it). As soon as the create() method execution is complete, the User object created there would go out of scope and will be marked for GC. The User object created in this method will eventually be GC-ed.
Things can be injected in two ways in a Spring MVC applications. And yes, you can you can mix injection and creation if doing right.
Components like the controller in your example are singletons managed by the application context. If you inject anything to them it is global, not per request or session! So a user is not the right thing to inject, a user directory can be. Be aware of this as you are writing a multithreaded application!
Request related things can be injected to the method like the used locale, the request, the user principal may be injected as parameters, see a full list at Spring MVC Documentation.
But if you create a model attribute you may use new() to create it from scratch. I will not be filled by spring but to be used by your view to display data created by the controller. When created in the request mapped method that is ok.
I'm building a straight forward AJAX / JSON web service with Spring. The common data flow is:
some DTO from browser
v
Spring #Controller method
v
Spring #Service method
I'm looking for the most easy way to handle data validation.
I know the #Valid annotation which works pretty well inside #Controller methods.
Why does #Valid not work within #Service methods?
I mean: A service method can be used by any other service and controller. So wouldn't it make much more sense to validate at #Service level?
Let's take this simple example:
MyDTO.java:
public class MyDTO {
#NotNull
public String required
#Min(18)
public int age;
}
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO) {
// persist myDTO
// and return created domain object
}
MyController.java:
#Autowired
MyService myService;
#Autowired // some simple bean mapper like Dozer or Orika
Mapper mapper; // for converting domain objects to DTO
#RequestMapping(...)
public MyDomainObjectDTO doSomething(#RequestBody MyDTO myDTO) {
mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class);
}
Is it common practice that the service method receives the DTO?
If yes: What's the best practice to validate that DTO inside the service method?
If no: Should maybe the controller manipulate the Domain object and just let the service save that object? (this seems pretty useless to me)
In my opinion the service should be responsible for only data consistency.
How do you solve this?
My answer? Both.
The service must check its own contract for validity.
The controller is part of the UI. It should validate and bind for a better user experience, but the service should not rely on it.
The service cannot know how it's being called. What if you wrap it as a REST service?
The service also knows about business logic violations in a way that no UI can. It needs to validate to make sure that the use case is fulfilled appropriately.
Double bag it; do both.
See my other answer: Check preconditions in Controller or Service layer
If you really want to do validation like error handling in your Service layer similar to Spring MVC you can use javax.validation and AspectJ (to advice the methods to validate) which is what I do because I like making reflection do the work and declarative programming (annotations).
Spring MVC doesn't need to do AspectJ/AOP to do the error handling because the methods are being called through reflection (url routing/dispatching).
Finally for you MVC code you should know that #Valid is sort of unofficially deprecated. Instead consider #Validated which will leverage more of the javax.validation features.
Let's imagine we have such a component in Spring:
#Component
public class MyComponent {
#Value("${someProperty}")
private String text;
}
If we define the property placeholder:
<context:property-placeholder location="classpath:myProps.properties"/>
And myPropos.properties contains the value for someProperty the value will be injected to the text field when the context is initialized. That's quite simple and easy.
But let's say that I have a service that enables user to change the value of the someProperty:
public void changeProp(String name, String newValue);
Is there a chance I can re-inject the newValue to text field. I mean it should be quite straight forward.. Basically it's nothing different than the after-initialization injection. I can not imagine that Spring does not have support for this? Can I fire some event or something?
I could do this on my own basically, but I wander is it maybe something there already? If not does anyone know what Spring class is in fact handling the injections at the first place? I could probably reuse the code there do perform this on my own if a solution does not exists.
I expect spring does not have a support for this, because the normal injection is done while creating the bean, but not will it is put in service.
Anyway: in this blog entry "Reloadable Application Properties with Spring 3.1, Java 7 and Google Guava", you can find the idea for an solution.
The key idea is to use a post processor to build a list of all fields with property fields. And if the properties are changed on can use this list to update the fields.
We are using Jersey, Jackson and Spring service (#service) annotation to expose some REST based Web-Services. Request and response data are exchanged in JSON Format.
Below is the Service Request Object content:
public class ServiceRequest{
private RequestHeader requestHeader;
private List<BaseEntity> requestData;
}
All specific entities will extend from BaseEntity class. For example :
public class User extends BaseEntity{
private String userName;
}
For all service operation we accept only ServiceRequest Object by passing list of request data objects. Now when we try to call these operation from REST Client, these are failing with
userName is not found as part of BaseEntity.
This is because while converting, Jersey/Jackson tries to autodetect the incoming field names with the specified object's property.
I want to know is there any way, I can handle this in an intelligent way. We do not have an option to change the signature of the Service. Really appreciate your help on this.
The below link has the answer for my question. Thank you for the support.
Polymorphism in jackson annotations: #JsonTypeInfo usage
Did you tried to use generics? You can declare concrete class type at Resource's to inform Jackson to map to specific type