What system configuration or malfunction in a shared hosting environment can null read-only static variables? - shared-hosting

I have an ASP.Net 4.0 website on a shared hosting system. Applications are recycled after 20 minutes of inactivity.
In my application some static variables are initialized in application_start.
When the next request comes in, the application should be restarted, application_start executed and the static variables reset.
After the period of inactivity, when I access pages that depend on the static vars, they are null and that creates errors.
Since these variables are initialized in application_start, it seems odd that after the period of inactivity that they would be null since the application restarting would reinitialize them.
In fact, when I see the null reference errors, recycling the app pool (and executing application_start) solves the problem until the next time the application is dropped from memory.
I'm wondering if some other type of system memory problem is occurring when the application is removed from memory, because if the application was simply being recycled, the reinitialization of the static variable in application_start would mean there would be no reason for the statics to be null.
Since static variables are not garbage collected they should never be null after initialization.
The errors never occur on any developer machines, only on the shared hosting system. What could be some other causes for static variables initialized in application_start to become null?
There is no code that resets the variables. They are private fields that only contain access via a get method.
Code:
private static List<State> stateList;
public static void LoadStaticCache()
{
var service = DependencyResolver.Current.GetService<ILocationService>();
stateList = service.GetAllStates().ToList();
}
public static List<State> GetStates()
{
return stateList;
}
When the inactivity period is met, the next time the stateList is accessed, it is null.
However, it is always initialized in application_start. How can it ever be null unless it is a system problem?
protected void Application_Start()
{
StaticCache.LoadStaticCache();
}
Recycling the Application Pool fixes the issue 100% of the time.

It sounds like your issue is related to session timeout.
Unlike earlier versions of IIS, if your hosted server is running IIS 7.0 or higher with Integrated Mode, Application_Start will not have access to the current HTTP context since it doesn't exist yet. IIS 7.0 in Classic Mode will have no issues.
In either case, a solution would be to move your initializations to Session_Start in Global.asax:
//protected void Application_Start()
//{
// StaticCache.LoadStaticCache();
//}
protected void Session_Start(object sender, EventArgs e)
{
StaticCache.LoadStaticCache();
}

Related

WebApplicationFactory and TestServer in integration tests for ASP.NET Core

I have two integ test classes defined as below. When I run tests in ApiControllerIT, all runs successfully. The same for FoundationControllerIT. However, when I run both together (by running the enclosing folder), tests fail.
The error message is:
Scheduler with name 'DefaultQuartzScheduler' already exists.
I have this definition in my Startup.cs file:
services.AddSingleton (IHostedService, QuartzHostedService);
So obviously this line causes the issue (if I remove this line, all testing together runs OK). So my question is - I'm a newbie from Java.. so I don't have a very good insight into .NET Core Integ test framework, but my understanding is - TestServer is created for each of test classes, e.g. One TestServer for ApiControllerIT, and the other for FoundationControllerIT. Is this incorrect? I'm just frustrated how come I'm getting a message:
Scheduler with name 'DefaultQuartzScheduler' already exists.
when I run two separate test classes?? How come the TestServers interfere each other?
public class ApiControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public ApiControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
public class FoundationControllerIT : IClassFixture<WebApplicationFactory<Startup>>
{
private readonly WebApplicationFactory<Startup> _factory;
public FoundationControllerIT(WebApplicationFactory<Startup> factory)
{
_factory = factory;
}
// tests ...
}
I might a bit late on this but I also had this problem and it might still be useful for others in the future.
The problem comes because the WebApplicationFactory will create two instances of your Startup class. This is drastically different from your normal service start, where you only have one instance of Startup.
(It might be a bit different in your case, but I am using a Singleton instance to create and manage my Schedulers throughout my application.)
The WebApplicationFactory also calls ConfigureServices and Configure on both of them. So even your singletons will be there twice, one for each Startup instance. This is not a problem because the Startup instances will have their own ServiceProvider. It only comes to problems if (multiple) singleton instances access the same static properties of something. In our case, this is the SchedulerBuilder using SchedulerFactory using SchedulerRepository within Quartz, which is a >real< singleton and uses this code:
/// <summary>
/// Gets the singleton instance.
/// </summary>
/// <value>The instance.</value>
public static SchedulerRepository Instance { get; } = new SchedulerRepository();
This means that your independent Singleton classes still use the same SchedulerRepository within Quartz, which explains why you get the exception.
Depending on what you are testing within your tests you have some options to tackle this issue.
The SchedulerRepository has a lookup method, which you could use to check if the Scheduler was already created by another instance: public virtual Task<IScheduler?> Lookup(string schedName, CancellationToken cancellationToken = default) - So you either just take the existing Scheduler or you generate another one with a different name
Catch the exception and do nothing. (this only really makes sense if your tests do not need Quartz, which is probably unlikely but I still wanted to list this option)
I cannot tell you what makes most sense in your case as this is completely dependent on what your application does and what you want to test, but I will probably stick with one variant of option 1.

How to configure AutoMapper 9.0 in IIS hosted WCF application

I want to use AutoMapper 9.0 in a WCF project containing several services that will be hosted in IIS. I've only found one other related SO question but its dealing with a 10 year old version of AutoMapper and is not asking the same question. Its answer is similar to the top hits on Google which suggest using a ServiceBehavior but that doesn't seem applicable when I want multiple services to use the same mapper. The defense rests.
In a web project, you might create a static MapperConfiguration in the Global.asax when the application starts, but WCF doesn't have a Global.asax. It looks like there are a few options for executing initialization code in WCF:
Include an AppInitialize() method in the App_Code folder. This will be dynamically compiled at runtime and people have complained that it can have missing reference issues in IIS so I'm not confident AutoMapper or its dependencies will be found once deployed to IIS.
Create a custom ServiceHost. This seems like it would execute once when the application starts, but also looks like it ignores the web.config configuration, which I don't want.
Use the Configure method per service. This has the same drawback as #2 and also I become concerned with thread safety (as in the ServiceBehavior approach) since two services could try to initialize the MapperConfiguration at once.
I considered just creating a class with a static property that would create a static MapperConfiguration or IMapper instance if it was not already created, but as in #3, I'm worried this may not be thread safe. Maybe if I did something like this?
public static class MapperConfig
{
private static IMapper _modelMapper;
private static readonly object _mapperLocker = new object();
public static IMapper ModelMapper
{
get
{
lock(_mapperLocker)
{
if (_modelMapper == null)
{
var config = new MapperConfiguration(cfg => cfg.AddProfile(new MappingProfile1()));
_modelMapper = config.CreateMapper();
}
}
return _modelMapper;
}
}
}
Where two services may call ModelMapper simultaneously. Another downside of this is the first request to any service will have to wait for the mapping to compile, but I'm not sure I can get away from that. I definitely don't want it compiling the mappings per call and would prefer not to even have to do it per service. Can you advise on the thread safety of MapperConfiguration and the best way to use it in IIS-hosted WCF?

Project Reactor Schedulers elastic using old threadlocal value

I am using spring webflux to call one service from another via Schedulers.elastic()
Mono<Integer> anaNotificationCountObservable = wrapWithRetryForFlux(wrapWithTimeoutForFlux(
notificationServiceMediatorFlux.getANANotificationCountForUser(userId).subscribeOn(reactor.core.scheduler.Schedulers.elastic())
)).onErrorReturn(0);
In main thread i am setting one InhertitableThreadLocal variable and in the child thread I am trying to access it and it is working fine.
This is my class for storing threadlocal
#Component
public class RequestCorrelation {
public static final String CORRELATION_ID = "correlation-id";
private InheritableThreadLocal<String> id = new InheritableThreadLocal<>();
public String getId() {
return id.get();
}
public void setId(final String correlationId) {
id.set(correlationId);
}
public void removeCorrelationId() {
id.remove();
}
}
Now the issue is first time its working fine meaning the value i am setting in threadlocal is passed to other services.
But second time also, it is using old id(generated in last request).
I tried using Schedulers.newSingle() instead of elastic(), then its working fine.
So think since elastic() is re-using threads, thats why it is not able to clear / or it is re-using.
How should i resolve issue.
I am setting thread local in my filter and clearing the same in myfiler
requestCorrelation.setId(UUID.randomUUID().toString());
chain.doFilter(req,res)
requestCorrelation.removeCorrelationId();
You should never tie resources or information to a particular thread when leveraging a reactor pipeline. Reactor is itself scheduling agnostic; developers using your library can choose to schedule work on another scheduler - if you decide to force a scheduling model you might lose performance benefits.
Instead you can store data inside the reactor context. This is a map-like structure that’s tied to the subscriber and independent of the scheduling arrangement.
This is how projects like spring security and micrometer store information that usually belongs in a threadlocal.

How to keep vaadin application instances from interfering with eachother?

I've got a Vaadin application and I'm getting some strange behaviour when running two instances of the application at the same time (one in FF, another in IE). I've already removed most static objects (these caused the application to completely reload when used parallel to another open application) and now I can interact normally with the UI without the complete reset. However, I'm now noticing that I'm getting only one user's data in both interfaces. I assume this is caused by singleton objects I'm using to manage some data caching and a SOAP connection. I'd like to know if it's the singleton pattern itself that's causing the strange output or is it just the static instance object I'm keeping?
I've tried using ThreadLocal with my singleton, but all my variables are always null when I try to use them in my singleton's functions. Currently my singleton contains this, which is probably terribly, terribly wrong since it doesn't work.
private static ThreadLocal<SoapClient> instance = new ThreadLocal<SoapClient>();
public static synchronized SoapClient getInstance(){
if (instance.get() == null) {
instance.set(new SoapClient());
}
return instance.get();
}
I chose a singleton object so I'd always have access to the cached data and my user's soap connection everywhere in my application instance, and the only other way I can think of for doing that is to have a static object somewhere, but the static keyword seems to be the cause of all my problems in the first place. Is there any way around this or is there something else causing it?
A better way to instantiate your thread local would be this
ThreadLocal<SoapClient> instance = new ThreadLocal<String>() {
#Override
protected String initialValue() {
return new SoapClient();
}
}
However, your problem here is web app servers "pool" and re-use threads. In Vaadin terms,not every request for an application is processed same thread - i.e. Thread1 could process requests for both App instance 1 and App Instance 2. If your SoapClient caches information appropriate to App instance 1, the UI for App 2 could end up using the SoapClient for App 1.
Assuming (from your description) that "app specific" information is cached in the SoapClient, I would suggest that you
Create and store the SoapClient on your Application object as a normal field (not static, not threadlocal)
If you need to access the application (in order to get the SoapClient), and it's tricky from where you are, use the ThreadLocal access pattern. See the second example on the link. Note that the ThreadLocal is set at the beginning of the HttpRequest, and "unset" at the end, ensuring that any subsequent requests on the same thread do NOT get the same application instance.

WCF data persistence between sessions

We are developing a WCF based system. In the process we are trying to lock some data from being modified by more than one users. So we decided to have a data structure that will contain the necessary information for the locking logic to execute (by for example storing the ID of the locked objects)
The problem we are having is persisting that data between sessions. Is there anyway we can avoid executing expensive database calls?
I am not sure how can we do that in WCF since it can only persist data (in memory) during an open session.
Static members of the service implementing class are shared between sessions & calls.
One option would be to use static members as Jimmy McNulty said. I have a WCF service that opens network connections based on a user-specified IP address. My service is configured for PerCall service instance mode. In each session, I check a static data structure to see if a network connection is already opened for the specified IP address. Here's an example.
[ServiceContract]
public interface IMyService
{
[OperationContract]
void Start(IPAddress address);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public class MyService : IMyService
{
private static readonly List<IPAddress> _addresses = new List<IPAddress>();
public void Start(IPAddress address)
{
lock(((ICollection)_addresses).SyncRoot)
{
if (!_addresses.Contains(address)
{
// Open the connection here and then store the address.
_addresses.Add(address);
}
}
}
}
As configured, each call to Start() happens within its own service instance, and each instance has access to the static collection. Since each service instance operates within a separate thread, access to the collection must be synchonized.
As with all synchronization done in multithreaded programming, be sure to minimize the amount of time spent in the lock. In the example shown, once the first caller grabs the lock, all other callers must wait until the lock is released. This works in my situation, but may not work in yours.
Another option would be to use the Single service instance mode as opposed to the PerCall service instance mode.
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class MyService : IMyService
{ ... }
From everything I've read, though, the PerCall seems more flexible.
You can follow this link for differences between the two.
And don't forget that the class that implements your service is just that - a class. It works like all C# classes do. You can add a static constructor, properties, event handlers, implement additional interfaces, etc.
Perhaps a caching framework like velocity help you out.
Create a second class and set its InstanceContextMode to single and move all the expensive methods there, then in your original class use that methods.