How to expose different path of an operation? - springdoc

I have a spring boot application which is located behind a reverse proxy. This proxy rewrites paths.
In my application I have a REST controller and document it with springdoc
#Operation(summary = "Expose some data", ...)
#RequestMapping(path = "/a", produces = MediaType.APPLICATION_JSON_VALUE, method = RequestMethod.GET)
public MyDto getA() {
The springdoc / OpenAPI generation leads to an operation reachable at /a
However the reverse proxy makes it available at /b
How can I tell springdoc that it should not use the introspected path from the #RequestMapping annotation but instead pass a path to any springdoc annotation?
Thanks.

Related

Startup.cs error (ASP.Net Core configuration)

I am trying to set up an ASP.Net Core application to read in configuration settings from a json file. I am using VS2015 and .NetCore 1.0 (with .Net Core Tools preview 2). I am having problems getting a simple piece of boiler plate code to compile.
I am using the following code, which was published at
http://asp.net-hacker.rocks/2016/03/21/configure-aspnetcore.html
public Startup(IHostingEnvironment env)
{
// Set up configuration sources.
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddEnvironmentVariables();
if (env.IsDevelopment())
{
// This will push telemetry data through Application Insights
// pipeline faster, allowing you to view results immediately.
builder.AddApplicationInsightsSettings(developerMode: true);
}
Configuration = builder.Build();
}
However, the IDE/compiler complains that 'the name "Configuration" does not exist in the current context' (last line of code). The only suggestion from the IDE is to include Microsoft.Extensions.Configuration. However this is a namespace which does not contain an object or property named "Configuration".
In addition 'AddApplicationInsightsSettings' fails with does IConfigurationBuilder not contain a definition for AddApplicationInsightsSettings and no extension method AddApplicationInsightsSettings accepting a first argument of type IConfigurationBuilder could be found
Any suggestions please ?
Thanks
Simply add Configuration property to your Startup class, tutorial has missed this 'step':
public IConfigurationRoot Configuration { get; set; }
ConfigurationBuilder.Build() method just returns instance of IConfigurationRoot, that you should save, if need to get settings further in Startup class (in ConfigureServices method for example).
Regarding second error, looks like you didn't add the Application Insights dependency:
{
"dependencies": {
"Microsoft.ApplicationInsights.AspNetCore": "1.0.0"
}
}

Configuration of asp.net core using settings

I'm evaluating asp.net core and .net core and I'm not yet sure about some things. In the past it was possible to configure many components using the web.config out of the box.
To name some examples:
There was the membership-provider and I could implement many providers but I was able ton configure later which provider should be used. This was dependend of the use-case. Now I should use asp.net identity - but I can only find configurations that are performed in sourcecode.
Same for authentication. I can define "CookieAuthentication" and have to set the name, loginpath or the timeout within sourcecode. In the past I was able to set timeout, etc... via web.config.
Is there any way to configure partially these things out of the box from a config-file? Or is this not supported anymore and I have to implement this configuration on my own? In the past this was a really comfortable way.
In ASP.NET Core, Web.config file is used ONLY for IIS configuration, you cannot use it for application configuration, but there are new, better, more flexible configuration options that you can use.
There are multiple configuration sources that you can use, but in this example I'm using json. These examples are from working code in my SimpleAuth project.
You can configure things in startup from configuration files.
First you add a config file in json format that maps to your class. You can see my example class here, and the json file it maps from here
builder.AddJsonFile("simpleauthsettings.json", optional: true);
Then, in the ConfigureServices method you configure your class to be wired up from the config system as shown
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
Then you add an IOptions accessor of your class to the method signature of the Configure method in the Startup.cs
The Dependency Injection will inject it into that method for you so you can use it there to configure things. Specifically I'm setting the cookie authentication scheme and name from my settings object.
The noteworthy part is that you can add whatever you want to the Configure method signature, and as long as it is something that has been registered in the ConfigureServices method, the DI will be able to inject it for you.
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
// this file is the custom configuration file to hydrate my settings from
builder.AddJsonFile("simpleauthsettings.json", optional: true);
....
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
....
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
....
}
// note that the DI can inject whatever you need into this method signature
// I added IOptions<SimpleAuthSettings> authSettingsAccessor to the method signature
// you can add anything you want as long as you register it in ConfigureServices
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IOptions<SimpleAuthSettings> authSettingsAccessor
)
{
...
// Add cookie-based authentication to the request pipeline
SimpleAuthSettings authSettings = authSettingsAccessor.Value;
var ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = authSettings.AuthenticationScheme,
CookieName = authSettings.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
LoginPath = new PathString("/Login/Index"),
Events = new CookieAuthenticationEvents
{
//OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}
};
app.UseCookieAuthentication(ApplicationCookie);
// authentication MUST be added before MVC
app.UseMvc();
}
}

DataSourceInitializer is not working on Spring boot 1.2

I am new to Spring boot.I want to add some sql while database is creating like seed data.
#Value("classpath:com/foo/sql/db-test-data.sql")
private Resource dataScript;
#Bean
public DataSourceInitializer dataSourceInitializer(final DataSource dataSource) {
final DataSourceInitializer initializer = new DataSourceInitializer();
initializer.setDataSource(dataSource);
initializer.setDatabasePopulator(databasePopulator());
return initializer;
}
private DatabasePopulator databasePopulator() {
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScript(dataScript);
return populator;
}
props.put("hibernate.query.substitutions", "true 1, false 0");
props.put("hibernate.hbm2ddl.auto", "create-drop");
props.put("hibernate.show_sql", "false");
props.put("hibernate.format_sql", "true");
I have perform this action.But it not working on spring boot.Can any one help me.
Sometimes spring-boot gets more in the way than it helps; IMHO this is especially so with web applications.
What you can do to get around this is to rename the bean that you define.
#Bean("springBootPleaseStopTellingMeHowYouThinkDataSourceInitializer")
public DataSourceInitializer dataSourceInitializer(DataSource dataSource) {
// build it.
}
Now, to turn off the built in bit that looks for data.sql in application.properties
spring.datasource.initialize=false
There, now boot is booted out of the way.
You can take advantage of Spring Boot database initialization capabilities. The simplest way is to place a "data.sql" file in the root of the classpath. So you just need to:
Change your sql file name to "data.sql".
Place it in "src/main/resources".
Spring Boot will automatically pick up the file and use it to initialize the database on startup.
You can check the documentation if you need to customize the file name, location, etc.

Pretty print JSON output of Spring Boot Actuator endpoints

Spring Boot Actuator provides several endpoints to monitor an application as:
/metrics
/beans
/health
...
Checking the endpoints with:
curl http://localhost:8080/metrics
results in:
{"counter.status.200.env":1,"counter.status.200.health":1,"counter.status.200.info":2,"counter.status.200.metrics":2,"gauge.response.env":5.0,"gauge.response.health":22.0,"gauge.response.info":1.0,"gauge.response.metrics":1.0,"mem":1030144,"mem.free":56118,"processors":8,"uptime":5108095,"instance.uptime":5102906,"heap.committed":1030144,"heap.init":262144,"heap.used":974031,"heap":3728384,"threads.peak":81,"threads.daemon":21,"threads":77,"classes":8854,"classes.loaded":8860,"classes.unloaded":6,"gc.ps_scavenge.count":119,"gc.ps_scavenge.time":7223,"gc.ps_marksweep.count":12,"gc.ps_marksweep.time":17573}
This is fine for machine consumption but hard to read by humans.
I'd like to format (i.e. pretty print) the JSON output of the Spring Boot Actuator endpoints to make them easier to read by operations personel.
Something like:
{
"counter.status.200.env":1,
"counter.status.200.health":1,
"counter.status.200.info":2,
"counter.status.200.metrics":2,
"gauge.response.env":5.0,
"gauge.response.health":22.0,
"gauge.response.info":1.0,
...
}
I tried setting
http.mappers.json-pretty-print=true
but this setting didn't affect the Actuator output.
Is there a configuration to enable pretty print of the Spring Boot Actuator JSON output?
UPDATE:
The official sample works for me.
It's important to follow the comments from #DaveSyer: the property to set is
http.mappers.jsonPrettyPrint=true
Investigation is still under way.
In the meantime I use the the json pretty print command line as workaround:
Install jsonpp (e.g. for OS X):
brew install jsonpp
Then pipe the curl output trough jsonpp which formats the json file on the fly:
curl http://localhost:8080/metrics | jsonpp
Results in:
{
"counter.status.200.env": 1,
"counter.status.200.health": 1,
"counter.status.200.info": 2,
"counter.status.200.metrics": 2,
...
}
As per http://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper, the official way to enable pretty print with Jackson in Spring Boot (1.2.2 at least) is to set the following property:
# Pretty-print JSON responses
spring.jackson.serialization.indent_output=true
For Spring Boot 1.5.1 I have in my YML file:
spring:
jackson:
serialization:
INDENT_OUTPUT: true
#BertrandRenuart answer was the closest, but by IDE did not see indent_output as correct.
The "http.mappers" property works for me but I think you might need it camel cased ("jsonPrettyPrint").
Do the following:
#Configuration
public class JacksonConfig {
#Autowired
private ObjectMapper objectMapper; //reuse the pre-configured mapper
#PostConstruct
public void setup() {
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
//whatever else you need
}
}
This works because Spring Boot uses an ObjectMapper bean to perform all the JSON related operations.
Note however that this configuration will pretty print all JSON outputs, not just the actuator related stuff.
UPDATE
The answer from #DaveSyer is obviously better! I hadn't found the HttpMapperProperties object which is used to configure Jackson. This is it's Javadoc
Actually I wanted to do the same. But then I asked: why? To debug my service better which comes with a small performance penalty.
Just use a browser extension, like this one :) to get a view like this one
With spring-boot 1.2.6, you need to use:
spring.jackson.serialization.INDENT_OUTPUT=true
From my log when using the old http.mappers.*:
http.mappers.json-pretty-print is deprecated. If you are using Jackson, spring.jackson.serialization.INDENT_OUTPUT=true should be used instead.
I use Python's commonly installed json.tool module:
curl --silent http://localhost:8080/metrics | python -mjson.tool
If you're using gson serialization with Spring, then none of the other answers will work for you. You'll have to use this configuration option:
spring.gson.pretty-printing=true
Confirmed working with Spring Boot as of version 2.0.3.Release.
I use jq for pretty printing JSON as well as filtering it. It's basically sed for JSON. On the mac, it can be installed with homebrew. (https://stedolan.github.io/jq/)
curl http://localhost:8080/metrics | jq
Instead of using curl I like to use httpie as a http command line client:
http http://localhost:8080/metrics
This would already format and syntax highlight the json response without having to pipe the output into another command. Also the command syntax is a bit more human friendly.
Spring Boot Actuator uses its own isolated ObjectMapper instance by default in which indent-output is disabled. To enable pretty-print of actuator output, you must set the following properties:
spring.jackson.serialization.indent-output=true
management.endpoints.jackson.isolated-object-mapper=false
Unfortunately, the application property
spring.jackson.serialization.INDENT_OUTPUT
did not work for me (spring boot versions 1.2.6 to 1.4.0.RELEASE). Instead, in my extension of WebMvcConfigurerAdapter, I've overridden configureMessageConverters() and added my own Jackson2ObjectMapperBuilder:
#Configuration
#EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
...
private MappingJackson2HttpMessageConverter jacksonMessageConverter() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.featuresToDisable(SerializationFeature.FAIL_ON_EMPTY_BEANS,
SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)
.featuresToEnable(SerializationFeature.INDENT_OUTPUT).modulesToInstall(hibernate4Module());
// can use this instead of featuresToEnable(...)
builder.indentOutput(true);
return new MappingJackson2HttpMessageConverter(builder.build());
}
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(jacksonMessageConverter());
super.configureMessageConverters(converters);
}
...
}
That seem to do the trick for me on Spring boot 1.4.0.RELEASE and my actuator output is now pretty printed (along with every other json output)
Here is my Emacs function to retrieve Spring Actuator Json from endpoints:
(defvar my/spring-actuator-server-history nil)
(defvar my/spring-actuator-last-server "http://localhost:8080")
(defvar my/spring-actuator-path-history nil)
(defvar my/spring-actuator-path-completion
'("actuator" "auditevents" "autoconfig" "beans" "configprops" "dump" "env" "flyway" "health" "heapdump"
"info" "jolokia" "liquibase" "logfile" "loggers" "mappings" "metrics" "shutdown" "trace")))
(defun my/spring-actuator (server path)
(interactive (list (read-string "Server: " my/spring-actuator-last-server 'my/spring-actuator-server-history)
(completing-read "Path: " my/spring-actuator-path-completion nil nil "" 'my/spring-actuator-path-history)))
(setq my/spring-actuator-last-server server)
(let ( (bufname (format "actuator: %s" path)) )
(when (get-buffer bufname)
(kill-buffer bufname))
(switch-to-buffer (url-retrieve-synchronously (format "%s/%s" server path)))
(rename-buffer bufname)
(goto-char (point-min))
(re-search-forward "^$" nil 'move)
(forward-char)
(delete-region (point-min) (point))
(json-pretty-print-buffer)
(json-mode) ))
If you don't like dependency on external json-mode library replace it with js-mode.
In case somebody with Spring Boot 2 (2.1.1 in my case) stumbles over this question as I did: We faced the same problem, and none of the answers helped for 2.1.1.
So what we did was to replace the existing endpoint (health in our case) with a new one. I described it at the end of this answer. And yes, this limits our solution to this single endpoint, but on the other hand it has the advantage of being able to format the output in any way you want - including pretty print JSON, but also output styled HTML if requested (by a service technician in a browser in our case). Note the produces attribute of #ReadOperation to achieve that.
This is the latest as of 12/27/2022. The below works.
-For application.yml config.
spring:
jackson:
serialization:
indent-output: true
But the above config won't work, if you implement WebMvcConfigurer class. In that case, override like below to make it work.
#Override
public void extendMessageConverters( List<HttpMessageConverter<?>> converters ) {
for ( HttpMessageConverter<?> converter : converters ) {
if ( converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
jacksonConverter.setPrettyPrint( true );
}
}
}
this not working
spring.jackson.serialization.INDENT_OUTPUT=true
this is working spring.jackson.serialization.indent-output=true

Does Spring Support JSON Configuration?

Does anyone know if Spring has any extensions that allow for configuring its ApplicationContext via JSON (or really any other format) rather than XML? I couldn't find anything in the official docs, but I was wondering if there were any other open source extensions that could allow this.
Just to be clear, I'm not talking about configuring SpringMVC to set up a RESTful JSON-based web service or anything like that, just if it's possible to do Spring app configuration via JSON instead of XML.
As far as I know there is no project to support JSON as configuration source. It should be relatively easy to kick-start, (Spring container has no dependency on XML, it is just a way to construct bean definitions). However it is much more work than you might think.
Note that Spring provides xml-schema to assist you in writing correct XML. You won't get that much in JSON. Also many DSLs were built on top of Spring XML and custom namespaces support (spring-integration, mule-esb and others use it).
If you hate XML (many do), try out Java Configuration, available since 3.0 and improved in 3.1:
#Configuration
public class MyBeans {
#Bean
public Foo foo() {
return new Foo();
}
#Bean
public Bar bar() {
return new Bar(foo());
}
#Bean
public Buzz buzz() {
Buzz buzz = new Buzz();
buzz.setFoo(foo());
return buzz;
}
}
Interesting fact: thanks to some fancy proxying, foo() is called exactly once here, even though referenced twice.
Try JSConf library available on maven central, it's support Properties, HOCON and JSON format.
You can inject values from external file to your service and more !
Sample usage of JavaConfig :
You data stored on file app.conf
{
"root":{
"simpleConf":{
"url":"Hello World",
"port":12,
"aMap":{
"key1":"value1",
"key2":"value2"
},
"aList":[
"value1",
"value2"
]
}}
You service where your configuration must be inject
#Service("service")
public class Service {
#Autowired
private ConfigBean configBean;
}
Declare a interface to access your configuration values from your service
#ConfigurationProperties("root/simpleConf")
public interface ConfigBean {
String getUrl();
int getPort();
Map getAMap();
List getAList();
}
And your Spring configuration bean :
#Configuration
public class ContextConfiguration {
#Bean
public static ConfigurationFactory configurationFactory() {
return new ConfigurationFactory().withResourceName("app.conf") //
.withScanPackage("org.jsconf.core.sample.bean");
}
}