Managing Facebook object within a Controller - spring-mvc

This is a more general Spring question that isn't necessarily a Spring Social Facebook issue; however, I'm asking the question here because it is not clear to me how Spring is managing the Facebook reference that is passed into the controller constructor.
I'm running this in a Spring boot app, version 1.5.3.RELEASE.
I've googled around and have read many things about how scoped-proxies work and whether the Controller is a singleton and such; but something is still not clear to me with this particular use case. My concern is over whether or not two or more simultaneous request will cause one reference to interfere with the other. It seems to me that there will be a conflict regardless of the scoped-proxy solution. To address this concern, I injected a Facebook and ConnectionRepository object into the controller constructor wrapped in a Provider class.
#Inject
public CopyGroupController(
Provider<Facebook> facebook,
Provider<ConnectionRepository> connectionRepository) {
It appears to have injected meaningful data; but when attempting to run this code:
#PostConstruct
public void init() {
ConnectionRepository repo = connectionRepository.get();
this.userManager.createOrGetUser(
repo.findPrimaryConnection(Facebook.class));
}
This failure occurs:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
This creates more uncertainty because I thought the FacebookTemplate was being managed as a request or session scoped bean and that it would Inject as a Provider so the object would reside on ThreadLocale; so two or more concurrent requests will not conflict. Passing a request scoped bean in a controller singleton constructor doesn't make any sense to me either. So I'm puzzled as to why a user specific reference would even be passed into a constructor that should only be called once.
I've tried setting breakpoints in the constructor to verify whether or not there is a conflict; but The same error as above would occur. Could someone please explain to me whether or not this is an issue and if so; how is the best, most modern way to resolve it.
Any assistance would be greatly appreciated.
Thank you in advance.

You have to register a RequestContextListener
Here you can find the problem detail
And here you can get how to add in using spring boot

Related

HttpClient, seems so hard to use it correctly

just another question about the correct usage of HttpClient, because unless i am missing something, I find contradicting information about HttpClient in Microsoft Docs. These two links are the source of my confusion:
https://learn.microsoft.com/en-us/azure/architecture/antipatterns/improper-instantiation/#how-to-fix-the-problem
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#typed-clients
First one states that the best approach is a shared singleton HttpClient instance, the second that the AddHttpClient<TypedClient>() registers the service as transient, and more specifically (copied from that URL):
The typed client is registered as transient with DI. In the preceding
code, AddHttpClient registers GitHubService as a transient service.
This registration uses a factory method to:
Create an instance of HttpClient.
Create an instance of GitHubService, passing in the instance of HttpClient to its constructor.
I was always using AddHttpClient<TypedClient>() and feeling safe, but now i am puzzled again... And making things worse, I found this github issue comment by #rynowak which states:
If you are building a library that you plan to distribute, I would
strongly suggest that you don't take a dependency on
IHttpClientFactory at all, and have your consumers pass in an
HttpClient instance.
Why this is important to me? Because, I am in a process of creating a library that mainly does two things:
Retrieve an access token from a token service (IdentityServer4)
Use that token to access a protected resource
And I am following the typed clients approach described in the link 2 above:
//from https://github.com/georgekosmidis/IdentityServer4.Contrib.HttpClientService/blob/master/src/IdentityServer4.Contrib.HttpClientService/Extensions/ServiceCollectionExtensions.cs
services.AddHttpClient<IIdentityServerHttpClient, IdentityServerHttpClient>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5));
Any advises or examples of how a concrete implementation based on HttpClient looks like, will be very welcome.
Thank you!

Get same instance of a component registered with Autofac as InstancePerLifetimeScope in Global.asax methods as is injected into a controllers?

I have a situation where I need to manually instantiate some objects in Application_BeginRequest that are dependent on some of the same components that I've registered with Autofac. I'd like to use the same instances of components that I've registered with Autofac with InstancePerLifetimeScope for injection into my MVC and WebAPI controllers. My config for both MVC and Web API works as expected, and an example of a component registration looks like so:
builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();
Now I want to use that same instance in the class I'm instantiating in Application_BeginRequest. I've tried the following methods:
//Tried with MVC controllers
DependencyResolver.Current.GetService<MyDbContext>()));
AutofacDependencyResolver.Current.ApplicationContainer.Resolve<MyDbContext>()));
AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<MyDbContext>()));
//Tried with Web API controllers
GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(MyDbContext))
But none give me what I'm looking for, even at later points in the request lifecylce (ie, beyond BeginRequest). As an aside, I need this to work with the Web API configuration, but I tried the first 3 methods just to see if I could get any of the resolved instances to match up with what Autofac is injecting.
I have what I believe is a decent understanding of lifetime scopes in Autofac and my assumption is that the instances that are being resolved for my application's controllers are in a child scope that the none of the above 4 methods are pointed towards, but it's fuzzy to me what each of the above methods is trying to do in regard to which scope they are looking at and how they decide. What's even fuzzier is what lifetime scopes Autofac is automatically creating for the components that are ultimately injected into my controllers and when they're created.
Clarification on the points above would be a big bonus, but my primary question here is how do I get Autofac to hand me the same instances of registered components in Global.asax that it resolves for Web API and MVC controllers?
If you read up on this subject, you'll notice that folks mention that in most circumstances for a web application, InstancePerLifetimeScope and InstancePerRequest can be used interchangeably. What they don't mention are the exceptions where these two registrations behave differently. Gerrod has an excellent article on lifetime scopes inside of ASP.NET MVC/Web API applications and how they work in which he elaborates on this piece of info that most omit. Understanding this difference is crucial to this scenario, and his article cleared up any misunderstandings I had in regards to InstancePerLifetimeScope registration in relation to ASP.NET applications. It also made me realize that, because I need to share instances of resolved components across my MVC/Web API controllers and within the global.asax, InstancePerLifetimeScope is no longer a suitable means of registration for this application- I now need to use InstancePerRequest.
As per the docs, InstancePerRequest actually uses InstancePerMatchingLifetimeScope under the hood. What I need is a reference to the child scope that is tagged with "AutofacWebRequest" that lives under the root scope. This is the scope that both my MVC and Web API controllers resolve their dependencies from, since they both use the same tag. So how do I get a reference to that particular scope? This was my solution, and I'd love to know if there's a better way to do it.
First off, I need to change my registration from
builder.Register(c => new MyDbContext()).AsSelf().InstancePerLifetimeScope();
to
builder.Register(c => new MyDbContext()).AsSelf().InstancePerRequest();
Now, after I've built my container I have the following method:
private void SetDependencyResolversForMvcAndWebApi(ILifetimeScope container)
{
container.ChildLifetimeScopeBeginning += CaptureRequestLifetimeScope;
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
}
The only part that wasn't there before is the event subscription. Everytime my container creates a child scope, my event handler gets called. The event handler looks like this:
private void CaptureRequestLifetimeScope(object sender, LifetimeScopeBeginningEventArgs args)
{
if (args.LifetimeScope.Tag == MatchingScopeLifetimeTags.RequestLifetimeScopeTag)
{
//Get the ILifetimeScope created for components registered with InstancePerRequest
var requestScope = args.LifetimeScope;
//This is the same DbContext instance that will be injected into
//my WebAPI and MVC controllers
var context = requestScope.Resolve<MyDbContext>();
//do the rest of my stuff
}
}
I've tested this by holding onto a reference of the resolved DbContext that's resolved within the CaptureRequestLifetimeScope event handler and comparing it to the DbContext instances that are injected into my Web API and MVC controllers, and they are indeed pointing to the same object.
Well, I think you should try changing .InstancePerLifetimeScope() into .InstancePerRequest();
As Autofac says about InstancePerLifetimeScope:
When you resolve the instance per lifetime scope component, you get a single instance per nested scope (e.g., per unit of work).
So when you do Resolve<MyDbContext>() you are probably doing it in a different Lifetime scope than you controller (I guess it's because you're doing an explicit resolution); that's why you're getting a diffent instance.
InstancePerRequest instead:
Some application types naturally lend themselves to “request” type semantics, for example ASP.NET web forms and MVC applications. In these application types, it’s helpful to have the ability to have a sort of “singleton per request.”
The begin phase of your request is already in the request phase, so you shoud get the same instance there and inside your controllers.
Instance per request builds on top of instance per matching lifetime scope by providing a well-known lifetime scope tag, a registration convenience method, and integration for common application types.
Based on this, probably, you can also go for the .InstancePerMatchingLifetimeScope("myrequest"), but you will have to manually instanciate a Lifetime scope everywhere like this using(var scope1 = container.BeginLifetimeScope("myrequest")); I think is not so practical.
Obviously I suppose you will not use those elements outside of the request scope, or you will get an exception. In that case, you are forced to the MatchingLifetimeScope.
If you need more details, the Autofac guide is extremely clear.
DependencyResolver.Current.GetService<MyDbContext>()));
AutofacDependencyResolver.Current.RequestLifetimeScope.Resolve<MyDbContext>()));
are same. They get current request lifetime scope. If you resolve some instance here, it shares it with cotrollers. (In this stiuation, instance per request and instance per lifetime will be same. Because their lifetime is same).
AutofacDependencyResolver.Current.ApplicationContainer.Resolve<MyDbContext>()));
This wil be resolved from root container. That's why it will create another instance for request lifetime scope. This will not be shared. And this will live in root container. (If you have per request instance, this will give error).
I have tested first one. It shares instance resolved in Application_BeginRequest with mvc controllers but not with Api controllers.
Then I tried to get GlobalConfiguration.Configuration.DependencyResolver.GetRequestLifetimeScope() in Application_BeginRequest it returns null.
I think, if it's api request, Autofac doesn't start request lifetime yet in Application_BeginRequest (May be it's related .net).
So if it's api request and if we can't reach autofac request life time. I don't know how to share this instance with mvc and api controllers which is resolved in Application_BeginRequest.
May be Travis can make it clear.

Handling ClientBase faults and SimpleIOC

I am using SimpleIOC from mvvm-light along with the ViewModelLocator class / pattern provided to provide ViewModels with the correct dependencies injected. The problem I have is that the dependency that is being injected in to my ViewModel is a WCF ClientBase instance that can "break" if it encounters a fault. One example would be if the service it is trying to connect to doesn't exist it will cause a fault. I don't know how to handle this properly. Once the ClientBase derived class is in a fault state it will no longer work. The ViewModelLocator keeps injecting this broken instance of my service proxy so even if this service becomes accessible the proxy will error out when used because it can't recover from a faulted state. How should I deal with this?
I was able to figure this one out on my own. The answer was to create a wrapper around the ClientBase proxy class so that when a call created a fault, the wrapper class could properly handle the exception yet still be ready to handle the next call.

How to obtain HTTPServletRequest in AspectJ

I need to add some audit logs to some business methods that are not in the web tier. One of the requirements are to store in this audit logs the user that executed the business method and the IP of the remote terminal. I decided to use AspectJ to Audit all this methods to avoid contaminating them with no bussiness code. (Note: I'm not using Spring, this is an old Struts 1 webapp)
public void myMethod(Object param, HttpRequest request**){
//Bussiness code that never use request param
}
#After("bla bla matches myMethod")
public void myAdvice(JoinPoint jp){
Object request = (HttpServletRequest)jp.getArgs()[1];
//bla bla using the request to get user and IP
}
So my question is, does anyone have any suggestion to obtain in a better or elegant way the Servlet Request in the Advice? In fact, myMethod does not contain Audit code (that is really good) but now have a second parammeter that is not used directly by the method and can become confusing to other developers. Please do not recomend me to advice the Servlet instead the business method.
Logging the IP from myMethod already ties the method to the web tier (or at least a tier with a meaningful IP address). An HttpServletRequest isn't appropriate, obviously, but an implementation providing "useful" information about the context of the call would be.
If the goal is to remove any extra parameter to myMethod, my first thought would be to create a RequestProcessor that stores the "useful" info in a ThreadLocal, which would be used by the logging aspect.

How to invoke an EJB 3.1 non-zero-arguments constructor from a servlet?

I have a login.java servlet and, as its name says, it provides login facilities to my web application.
I'm a newbie and I'm using EJB 3.1 and EE 6. In my LoginBean.java EBJ I have a no-arguments constructor and another one that has some parameters (email, password, etc).
At certain point in the servlet code I have the calling to instantiate my EJB:
#EJB LoginBean loginBean;
I'd like to know if it's possible (and how) to call the other constructor instead of the zero-arguments one.
Thanks a lot.
Cheers.
You don't want to do that. The one and same servlet is shared among all users, so the EJB is also shared among all users. You don't want to store user-specific data as instance variable of the servlet or EJB class. It would be shared among all webpage visitors.
Rather move the arguments to a EJB method which you invoke in the doPost() method of the login servlet.
User user = loginBean.login(username, password);
and then store this in the HTTP session when it went successful
request.getSession().setAttribute("user", user);
so that the rest of your webapp can intercept on this to determine if the user is logged in or not.
if (request.getSession().getAttribute("user") != null) {
// User is logged in.
} else {
// User is not logged in.
}
I 100% agree with BalusC. In addition to his answer I would like to add that you normally* never explicitly reference the constructor of an EJB bean, even if doing so would theoretically make sense (e.g. when passing in some dependencies, or some configuration parameter).
EJB beans are managed objects and what you are getting in your #EJB annotated field is not the actual object but a stub (proxy). The actual object instance to which the stub points is most likely constructed long before you get this stub to it and also very likely comes from a pool.
(*)Some kind of units tests may be an exception to this rule.

Resources