I was looking at this SO question, but here I only want Caffeine to start reporting to JMX.
I have added an application.conf file as such and referenced it via -Dconfig.file:
caffeine.jcache {
# A named cache is configured by nesting a new definition under the caffeine.jcache namespace. The
# per-cache configuration is overlaid on top of the default configuration.
default {
# The monitoring configuration
monitoring {
# If JCache statistics should be recorded and externalized via JMX
statistics = true
# If the configuration should be externalized via JMX
management = true
}
}
It is not working, but I suspect it might be related to jcache, but not sure what is the expected way to implement this basic monitoring.
The cache instance is registered with the MBean server when it is instantiated by the CacheManager. The following test uses the programmatic api for test simplicity.
public final class JmxTest {
#Test
public void jmx() throws MalformedObjectNameException {
var config = new CaffeineConfiguration<>();
config.setManagementEnabled(true);
config.setStatisticsEnabled(true);
var manager = Caching.getCachingProvider().getCacheManager();
var cache = manager.createCache("jmx", config);
cache.put(1, 2);
var server = ManagementFactory.getPlatformMBeanServer();
String name = String.format("javax.cache:type=%s,CacheManager=%s,Cache=%s",
"CacheStatistics", manager.getURI().toString(), cache.getName());
var stats = JMX.newMBeanProxy(server, new ObjectName(name), CacheStatisticsMXBean.class);
assertThat(stats.getCachePuts()).isEqualTo(1);
}
}
If you do not need JCache for an integration then you will likely prefer to use the native APIs and metrics library. It is supported by Micrometer, Dropwizard Metrics, and the Prometheus client. While JCache is great for framework integrations, its api is rigid and cause surprising performance issues.
Related
Using VB.NET asmx project, which is hosted behind SSL offload, I need to change the generated WSDL to show https for the soap:address.
from: <soap:address location="http://example.com/example.asmx"/>
to: <soap:address location="https://example.com/example.asmx"/>
preferably outside of code so we can influence in the build process.
It depends what system are you using for generating the wsdl.
You shared that you are using VB.NET but it does not narrow down enough to answer your question a 100%. If you can show some code then we could help hopefully. Also as far as I remember, the location in the WSDL file is the same as the client is accessing it (the URL where it reaches). Meaning that as the offloading happens elsewhere the location could always be http.
Without further information I see three options for you:
Configure the TLS offloader to redirect the queries from http to httpS. (This is also a recommended setting from a security point of view.)
Where the offloading is happening use a solution to replace the content of the response. (This has the advantage of being specific to the environment.)
Use self singed certificate on the internal application as well, and therefore the address will be generated correctly. (This could be a bit tougher nut to crack, but has the benefit of not being dependent on other configuration and having to modify that configuration for every environment from development to live.)
In c# it could be done in code https://learn.microsoft.com/en-us/archive/blogs/kaevans/modify-a-web-services-wsdl-using-a-soapextensionreflector and is qite complicated. If you have a developer machine, then you need to use TLS as well... but here you go:
using System;
using System.Web.Services.Description;
namespace Msdn.Web.Services.Samples
{
public class HttpsReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
//no-op
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
foreach (Service service in description.Services)
{
foreach (Port port in service.Ports)
{
foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
{
SoapAddressBinding binding = extension as SoapAddressBinding;
if (null != binding)
{
binding.Location = binding.Location.Replace("https://", "https://");
}
}
}
}
}
}
}
I currently have a web app on .NET 6 with integration tests using WebApplicationFactory.
Here is a simplified version of my Program.cs file:
var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;
var configuration = builder.Configuration;
services.AddAuthentication()
.AddJwtBearer(o =>
{
var configs = configuration.GetRequiredSection("authOptions");
// using configs here
});
For most services I need to mock, I can remove them from the service descriptor. However, this would not work for services like adding authentication from what I have seen. Basically, I am looking for a way to mock the configurations for integration testing.
The AddJwtBearer also has no access to the IServiceProvider and thus cannot use the injectable IConfiguration. I would like to account for all such features that need to use the configuration from builder.Configuration.
I am trying something like this:
public class CustomWebApplicationFactory: WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(configBuilder =>
{
// remove all configs or at least user secrets from config builder
// add mocked configurations
});
}
}
I would like to remove the configuration so as to make sure in future if I add a configuration I forget to mock, the integration test would throw an exception instead of using the user secrets.
I suggest the following approach if you would like to clear any existing default configuration providers and then add your custom configuration.
public class CustomWebApplicationFactory: WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(configBuilder =>
{
//clears all the default configuration providers
configBuilder.Sources.Clear();
//Add your custom configuration from Json file or memory
});
}
}
You can find more examples here.
Hope this helps.
What's the best way to know if my app is running under Kestrel or HTTP.sys. All that I have found so far is to check for "Kestrel" in one of the HttpConext property class names.
Within an MVC controller I can do something like this:
Boolean IsKestrel = HttpContext.Features.GetType().ToString().Contains("Kestrel");
i.e. check this:
Features = {Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1Connection<Microsoft.AspNetCore.Hosting.HostingApplication.Context>}
When using HTTP.sys I only get:
Features = {Microsoft.AspNetCore.Http.Features.FeatureCollection}
(Is "Http" here enough to know that this is HTTP.sys?)
There must be a better way. Is there an obvious property somewhere that contains the name of the host being used?
A broader question might be, how do I know what the builder pattern built?
Update
Found something better, but still looking for a Property that has the server name or type.
In an MVC controller:
var isKestrel = HttpContext.Request.Headers.GetType().ToString().Contains(".Kestrel.");
var isHTTPsys = HttpContext.Request.Headers.GetType().ToString().Contains(".HttpSys.");
At the operating system level, netsh http show servicestate will list all active URLs listening via HTTP.SYS.
From code you can locate an instance of Microsoft.AspNetCore.Hosting.Server.IServer and check what its implementation is, in netcore 6:
Kestrel => Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerImpl
IIS ==> Microsoft.AspNetCore.Server.IIS.Core.IISHttpServer
HTTP.SYS => Microsoft.AspNetCore.Server.HttpSys.MessagePump
This relies on implementation details (so can break), also other extensions can change these e.g. CoreWcf creates CoreWCF.Configuration.WrappingIServer that wraps one of the above implementations.
you can use System.Diagnostics.Process.GetCurrentProcess().ProcessName
I am not sure whether you want to check this information using the code only or you are just looking for a way to know on which web server your app is running.
In my search result, I found that we could set the ports for a specific web server. When the application will run on that specific web server then it will use that pre-configured port. I am assuming your app also has a similar configuration. You could set the different ports for Kestrel, Http.sys, or IIS. By checking the port number you could say that on which web server your site is running.
You could try to go to the launchSettings.json file in your project where you could configure ports for IIS and Kestral.
Helpful References:
Kestrel Web Server in ASP.NET Core
Understand HTTP.sys Web Server In ASP.NET Core
Hello this is a good question, you question is asking how to find out from inside the code and not from a console.
OOB I did not find anything. So, I had to get very creative to figure this out, sorry for the typo's its brand new stuff...
Option 1:
Since the Kestrel section & endpoints are inside the appsettings.json I used that to find out if its hosted by Kestrel!
//Please create a static class to hold the config.
public static class MyStartupIsItKestrelConfiguration
{
public static IConfiguration Configuration;
public bool static IsKestrel()
{
//check your section kestrel??
var kestrel = configuration.GetSection("Kestrel");
// now check kestrel section or any other section
// see picture for kestrel endpoint in app setting sbelow
return true;
}
}
Now you can access it anywhere and see if you used Kestrel
//Now add it/save it in your startup and access later
public Startup(IConfiguration configuration)
{
Configuration = configuration;
MyStartupIsItKestrelConfiguration.Configuration = configuration;
}
Once you have this
//you can use it in ** YOUR CONTROLLER
MyStartupIsItKestrelConfiguration.IsKestrel();
Option 2:
Please check this public Microsoft.AspNetCore.Http.Features.IFeatureCollection Features { get; }
You can get the features public TFeature? Get<TFeature> (); as a Key Value Pair - and then check the feature for e.g. KESTREL DOES NOT ALLOW PORT SHARING
they split the features namespace in .net core 6 there are breaking changes
You should use the features collection
Link - https://github.com/spring-cloud-stream-app-starters/aggregator/tree/master/spring-cloud-starter-stream-processor-aggregator does not list property for gemfire message store
The GemfireMessageStore is configured like this:
#ConditionalOnClass(GemfireMessageStore.class)
#ConditionalOnProperty(prefix = AggregatorProperties.PREFIX,
name = "message-store-type",
havingValue = AggregatorProperties.MessageStoreType.GEMFIRE)
#Import(ClientCacheAutoConfiguration.class)
static class Gemfire {
#Bean
#ConditionalOnMissingBean
public ClientRegionFactoryBean<?, ?> gemfireRegion(GemFireCache cache, AggregatorProperties properties) {
ClientRegionFactoryBean<?, ?> clientRegionFactoryBean = new ClientRegionFactoryBean<>();
clientRegionFactoryBean.setCache(cache);
clientRegionFactoryBean.setName(properties.getMessageStoreEntity());
return clientRegionFactoryBean;
}
#Bean
public MessageGroupStore messageStore(Region<Object, Object> region) {
return new GemfireMessageStore(region);
}
}
The point is that you always can override that ClientRegionFactoryBean with your own.
Or you can take into account that ClientCacheAutoConfiguration is based on the #ClientCacheApplication, which, in turn, allows you to have a ClientCacheConfigurer bean and provide whatever is sufficient for your client cache configuration. Including config and pool. That's right: it is not on the app starter configuration level and you have to right some custom code to be included as a dependency into the final uber jar for target binder-specific application.
More info how to build them is here in Docs: https://docs.spring.io/spring-cloud-stream-app-starters/docs/Einstein.RC1/reference/htmlsingle/#_patching_pre_built_applications
A variety of backend storage options exist through Spring Integration. You can read more about it in spring-cloud-starter-stream-processor-aggregator/README.
Spring Integration docs on this matter are included as a link, and the Gemfire section could be useful.
It'd be also useful to review MessageGroupStore implementation, since it is the foundation for the storage option in aggregator.
so I have deployed my spring app on Heroku with 2 nodes and I noticed that if I add a product in the basket and I start refreshing the cart page, sometimes I see the product, sometimes the product is not there. So I'm thinking that maybe the request is hitting different nodes every time.
On the spring-session website I can see This can make clustering much easier. This is nice because the clustering setup is done in a vendor neutral way. Furthermore, in some environments (i.e. PaaS solutions) developers cannot modify the cluster settings easily. But I couldn't find how to make the settings for a sticky session with spring-session. My setup is just the one ouf of the box:
#Bean(name = { "defaultRedisSessionRepository", "sessionRepository" })
#ConditionalOnProperty(name = { "nemesis.platform.redis.url" })
public SessionRepository defaultRedisSessionRepository(RedisTemplate<String,ExpiringSession> redisTemplate) throws Exception {
return new RedisOperationsSessionRepository(redisTemplate);
}
then in my MVC config:
#Bean(name = {"defaultSessionFilter", "sessionFilter"})
public Filter sessionFilter() {
CompositeFilter compositeFilter = new CompositeFilter();
compositeFilter.setFilters(Arrays.asList(new SessionRepositoryFilter(applicationContext.getBean("sessionRepository", SessionRepository.class)), applicationContext.getBean(UrlEncoderFilter.NAME, UrlEncoderFilter.class)));
return compositeFilter;
}
and then in my WebApplicationInitializer:
final FilterRegistration sessionFilterChainReg = servletContext.addFilter("sessionFilter", DelegatingFilterProxy.class);
sessionFilterChainReg.addMappingForServletNames(EnumSet.of(DispatcherType.REQUEST, DispatcherType.ERROR, DispatcherType.ASYNC, DispatcherType.FORWARD, DispatcherType.INCLUDE), false, dispatcherServletReg.getName());
Spring Session does not setup sticky sessions. Instead, it allows any JVM to lookup the session object by placing it in a central datastore (i.e. Redis).