Spring Boot - Web Application Context Bean Scope - java

I have a class A as a bean.
public class A
{
// constructors
// properties
// getters and setters
}
Spring boot configuration:
#Configuration
public class AConfig{
#Bean
#Scope(scopeName = WebApplicationContext.SCOPE_APPLICATION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public A getA() {
return new A();
}
}
I am working right now with WebSocket and I am trying to get a new class A instance for some specific WebSocket channels, let's say if I am working with WebSocket id:1 then I will have the instance of A (some address) for that WebSocket, and for the WebSocket id:2 I will have another instance of A (some other address), and I can have it across application. How can I achieve that? In this case, I guess I have to send some ID to the server to identify the spring bean I am looking for.

**Instead of Autowired we should use Constructor arguments to make it loosely coupled **
class MessageSocketDemo {
private A a;
public MessageSocketDemo(A a) {
this.a = a;
}
public MessageSocketDemo() {
a = new A("address");
}
}
class A {
String address;
public A(String add) {
address = add;
}
}
So when you create object of MessageSocketDemo you create object of A every time new.
Or make the Scope of A as prototype or request which will create it new every time it is asked, and a lookup method to create instance of A

Related

How Inject prototype spring bean to singleton bean

I want to change my pojo class to spring, I have a problem for injection protoype bean to singelton bean, My old code was as follows:
public class InsertBankBusiness(){
private ServiceInput input;
public void doBusiness(ServiceInput input){
this.input = input;
....
}
},
public class BankService(){
public void definebank(ServiceInput input){
InsertBankBusiness insertBankBusiness = InsertBankBusiness ()
insertBankBusiness .doBusiness(input)
}
}
Insert BankBusiness class is not thread safe and I need to instantiate from it for every service call, I have now rewritten the code as follows:
#Component(value="insertBankBusiness")
#Scope(value="request", proxyMode=TARGET_CLASS)
public class InsertBankBusiness(){
private ServiceInput input;
public void doBusiness(ServiceInput input){
this.input = input;
....
}
},
#Service(value="bankService")
public class BankService(){
#Autowire InsertBankBusiness insertBankBusiness;
public void definebank(ServiceInput input){
insertBankBusiness.doBusiness(input)
}
}
Is the behavior of the second scenario the same as the first scenario?
Not the same.
In the first scenario, you create InsertBankBusiness service each time when access it, but in the second scenario, service creates once per HTTP request.
You need to use Prototype scope instead of Request to have the same behavior.
#Scope(value= "prototype", proxyMode=TARGET_CLASS)
public class InsertBankBusiness {
}
InsertBankBusiness injected correctly via Scoped Proxy. Each time the method on the proxy object is called, the proxy decides itself whether to create a new instance of the real object or reuse the existing one.

Convert legacy code to Spring dependency injection

The legacy code snippet is shown as below. What I want to do is to convert this code to Spring. But the problem is Spring managed the dependency on it's own. My question is how to inject the serviceId provided by constructor?
public class MyService{
public Attribute getAttribute(){
int serviceId =1;
new ServiceDao(serviceId).getAttribute();
}
}
class ServiceDao{
private int serviceId;
ServiceDao(int serviceId){
this.serviceId = serviceId;
}
public Attribute getAttribute(){
//to get attribute
}
}
Basically you are trying to create new objects each time you call
new ServiceDao(serviceId).getAttribute();
This is purely against dependency injection. As your logic is based on the service ID you can create a service class as follows
#Service
class ServiceDao{
ServiceDao(){
}
public Attribute getAttribute(int serviceId){
//to get attribute
//return attribute based on service Id,
//if(serviceId==1)
//{ return new Attribute("Red");}
}
}
Your Myservice can be something like this
#Service
public class MyService{
#Autowired
ServiceDao dao;
public Attribute getAttribute(){
int serviceId =1;
return dao.getAttribute(1);
}
}

How to bind a object with Guice in Dropwizard?

I want to use a bind object in my service class with guice in dropwizard.
Consider the object
public class MinioData {
private String endpoint;
public String getEndpoint() {
return endpoint;
}
}
And a service
#Path("/upload")
#Produces(MediaType.APPLICATION_JSON)
public class UploadResource {
private final MinioData minioData;
#Inject
public UploadResource(
#Named("miniodata") MinioData minioData) {
this.minioData = minioData;
}
How can I bind this object so that can be used in my service. For a String I could use
bindConstant()
.annotatedWith(Names.named("miniodata"))
.to(configuration.getMiniodata());
but since in this case it is a general object how would I bind it?
If you have an existing Guice module configured in your DW application, you can just bind the MinioData instance from the configuration object to the associated class:
binder.bind(MinioData.class).toInstance(configuration.getMiniodata());

A known design pattern for dynamic factory

Does this have a proper name?
public class SomethingFactory {
private final String someParameter;
public SomethingFactory(String someParameter) {
this.someParameter = someParameter;
}
public Something create(String anotherParameter) {
return new Something(someParameter, anotherParameter);
}
}
public class Something {
public final String someParameter;
public final String anotherParameter;
public Something(String someParameter, String anotherParameter) {
this.someParameter = someParameter;
this.anotherParameter = anotherParameter;
}
}
What's different from a regular factory is that you have to specify a parameter at runtime to create() whenever you need to create an object.
That way you can make a singleton factory within Spring context for example, configuring first half of parameters there, and then finish with the rest of parameters at runtime when you call create().
Why I need that in the first place if you're curious:
I used to have regular singleton objects in Spring context and it was fine in thread-per-request applications, but now my whole app is non-blocking and I can't use ThreadLocal to keep stuff throughout entire request processing. For example, to keep info on timings with something like Apache StopWatch.
I needed to find a way to implement a "request scope" in a multithreading, non-blocking environment without having to supply the object representing the scope in every method (that would be silly) of my code.
So I thought let's make every (service) class take this scope object in constructor and let's create those classes on every request, but that goes against the singletons. The singletons we're talking are like, UserService that logs a user in, or a CryptoService that generates digital signatures. They're configured once in Spring, injected wheneven needed and everything's ok. But now I need to create those service classes in every method where they're needed, instead of just referencing an injected singleton instance.
So I thought let's call those singletons "templates" and whenever you need an actual instance you call create() supplying the said scope object. That way every class has the scope object, you just have to keep supplying it into other template service constructors. The full thing would look like this:
public class UserService {
private final Scope scope;
private final Template t;
private UserService(Template t, Scope scope) {
this.t = t;
this.scope = scope;
}
public void login(String username) {
scope.timings.probe("before calling database");
t.database.doSomething(username);
scope.timings.probe("after calling database");
}
public static class Template { /* The singleton configured in Spring */
private Database database;
public void setDatabase(Database database) { /* Injected by Spring */
this.database = database;
}
public UserService create(Scope scope) {
return new UserService(this, scope);
}
}
}
public class LoginHttpHandler { /* Also a Spring singleton */
private UserService.Template userServiceT;
public void setUserServiceT(UserService.Template userServiceT) { /* Injected by Spring */
this.userServiceT = userServiceT;
}
public void handle(HttpContext context) { /* Called on every http request */
userServiceT.create(context.scope).login("billgates");
}
}
In Spring you'd just describe a UserService.Template bean with the appropriate dependencies it needs and then inject that bean whenever a UserService is needed.
I just call that a "template". But like always I feel it's already been done. Does it have any name?
That is almost the example given for Guice's AssistedInject:
public class RealPaymentFactory implements PaymentFactory {
private final Provider<CreditService> creditServiceProvider;
private final Provider<AuthService> authServiceProvider;
#Inject
public RealPaymentFactory(Provider<CreditService> creditServiceProvider, Provider<AuthService> authServiceProvider) {
this.creditServiceProvider = creditServiceProvider;
this.authServiceProvider = authServiceProvider;
}
public Payment create(Date startDate, Money amount) {
return new RealPayment(creditServiceProvider.get(), authServiceProvider.get(), startDate, amount);
}
}
public class RealPayment implements Payment {
public RealPayment(
CreditService creditService, // from the Injector
AuthService authService, // from the Injector
Date startDate, // from the instance's creator
Money amount) // from the instance's creator
{
...
}
}
Assisted injection is used to "create classes that need extra arguments at construction time".
Also, this is similar to partial application, so you could have a PartialUserService that creates a UserService.

Accessing main class from Jersey listener without the main class being a singleton object

I often use Jersey simple server as a webservice in my Java applications. Whenever I do this I only seem to be able to fetch properties from my application (main class) if it is setup as a singleton. So, I only seem to be able to fetch the information with MainClass.getInstance().
I know I can make the Jersey listener some sort of singleton in Jersey but this only means that the listener object will be instantiated once within Jersey in stead of for every single request: The listener is not a real singleton because it still needs a public constructor.
Is there a way to access my application class without it being a singleton object itself?
Here is the relevant code:
public class JerseyService {
private MainClass mainClass;
private int port = 8080;
private DefaultResourceConfig config;
private Closeable jerseyServer;
public JerseyService() {
config = new DefaultResourceConfig(JerseyListener.class); // Attach the listener (resource) to the Jersey server
jerseyServer = SimpleServerFactory.create("http://0.0.0.0:" + jerseyPort, config);
}
public String getData() {
return "somedata";
}
}
#Path("/")
public class JerseyListener {
#Path("getData")
#GET
#Produces("application/json")
public Response getData() {
// How can i call getData() from JerseyService
// without JerseyService being a singleton??
return Response.status(Response.Status.OK).entity("{<jsondata>}").build();
}
}

Categories