SpringFox Date format to milliseconds - documentation

I'm using SpringFox (Swagger) to document my REST APIs. One of the nice features in Swagger is to show example model and the data type format.
Now, I configured my APIs to produce and consume dates in milliseconds but when I'm looking at the sample JSON model the date format is following: "2015-09-21T00:51:32.617Z". See screenshot below. Is it possible to tell SpringFox (Swagger) how to format the date properly?

You could try:
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(getApiInfo())
.directModelSubstitute(YourDateTimeClass.class, Integer.class);
Basically you are telling Swagger to replace the date class with an Integer which could represent the milliseconds.

This is related to the underlying Jackson serialiser. You have to set the correct date format for it otherwise by default it's using timestamps.
Here is an example configuration
#Configuration
public class WebConfiguration extends WebMvcConfigurerAdapter {
#Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jsonMessageConverter = (MappingJackson2HttpMessageConverter) converter;
ObjectMapper objectMapper = jsonMessageConverter.getObjectMapper();
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
break;
}
}
}
}
This way it will use an ISO-8601 date-time format. Here is another blog post that explains how to set your own preferred date format: http://yysource.com/2016/06/change-default-date-for-jackson-in-spring-boot-application/

I got a similar problem as yours, and I resolved it by adding the following config in my Spring Boot's application.properties file:
spring.jackson.date-format=com.fasterxml.jackson.databind.util.ISO8601DateFormat

Related

NHibernate5: converting dates to local dates when they're persisted without a specific kind

Now that NHibernate 5 is out, I was wondering what's the recommended approach to load dates as local dates when they're persisted as datetime2 in a SQL Server 2016 database. Until now, dates were interpreted as local (so, the properties ended up with the correct values), but now, the behavior has changed and I'm unable to use the LocalDateTime.
Unfortunately, my donmain's behavior relies in getting those dates automatically loaded as local dates...
Any pointers on how to solve this?
Thanks,
Luis
Since I didn't found a way to disable this behavior, I've ended up creating a new type that will simply adjust the format of the data (considering always that it was saved in local format):
public class LocalDateTimeTypeNoThrow : LocalDateTimeType {
public LocalDateTimeTypeNoThrow() {
}
public LocalDateTimeTypeNoThrow(DateTimeSqlType sqlType) : base(sqlType) {
}
public override string Name => "LocalDateTimeNoThrow";
public override void Set(DbCommand st, object value, int index, ISessionImplementor session) {
var dateValue = (DateTime) value;
//removed throwing from here
st.Parameters[index].Value = AdjustDateTime(dateValue);
}
}
If there's a better way, please let me know.
Luis

Set the default __toString() format per Carbon instance?

I retrieve dates from a database and have the option to pre-process them (via the Laravel framework (v5.2)). The dates or times can come in any particular format but for this example let's say Y-m-d.
I want to be able to access the date as a Carbon instance in the view — this would give me the flexibility to format the date however I please or do nothing with it and print as-is (with the default toString being the same as its original string format).
The issue is maintaining the default expected toString format at the top-level Carbon toString format.
According to the docs, you can use the ::setToStringFormat() method to change the default format of toString. It is possible to set it with the static method Carbon::setToStringFormat() but it also works as an instance method e.g. ($date = Carbon::now())->setToStringFormat('Y-m-d') - albeit this seems to behave identically to the static method.
So, is it possible to set the individual __toString() format for a date instance?
It would allow me to do the following:
public function getDateAttribute($value)
{
$date = Carbon::createFromFormat('Y-m-d', $value);
// $date->setToStringFormat('Y-m-d');
return $date; // prints in 'Y-m-d' format
}
In a view, I would then chain methods on the date, or print it as-is.
I had the same sort of issue and worked my way around it
First create a global serialization method for carbon dates (e.g. in the boot of the Laravel AppServiceProvider)
<?php
namespace App\Providers;
use Illuminate\Support\Carbon;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider {
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot() {
// ...
Carbon::serializeUsing(function (Carbon $carbon):string {
$format = $carbon->getSettings()['toStringFormat'] ?? 'Y-m-d\TH:i:s';
return $carbon->format($format);
});
// ...
}
// ...
}
Then set the 'toStringFormat' setting to the format you need
$someCarbonDate->settings([ 'toStringFormat' => 'Y-m-d' ]);
Carbon::serializeUsing will now check if the carbon being serialized has a toStringFormat and use that or it will fall back to some other format you define.
You could probably also create your own Carbon class and extend Carbon\Carbon or Illuminate\Support\Carbon (used by Laravel) and override the __toString method, but that creates some new challenges when used in combination with the casting Laravel does internally.
If you just want to set the default format for when rendering Blade templates you can use the Blade::stringable method.
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot() {
// ...
Blade::stringable(function(\Illuminate\Support\Carbon $dateTime) {
return $dateTime->format('d/m/Y H:i:s');
});
// ...
}
// ...
}
Any Illuminate\Support\Carbon instances should automatically be rendered with this format unless you choose otherwise.
For example...
{{ $user->created_at }} would now render as 23/07/2021 10:16:24 by default
{{ $user->created_at->toDateString() }} still works and would render as 23/07/2021
NOTE: You might need to run php artisan view:clear to clear any compiled views before this takes effect 🙂

Only show effective SQL string P6Spy

I'm using p6spy to log the sql statements generated by my program. The format for the outputted spy.log file looks like this:
current time|execution time|category|statement SQL String|effective SQL string
I'm just wondering if anyone knows if there's a way to alter the spy.properties file and have only the last column, the effective SQL string, output to the spy.log file? I've looked through the properties file but haven't found anything that seems to support this.
Thanks!
In spy.properties there is a property called logMessageFormat that you can set to a custom implementation of MessageFormattingStrategy. This works for any type of logger (i.e. file, slf4j etc.).
E.g.
logMessageFormat=my.custom.PrettySqlFormat
An example using Hibernate's pretty-printing SQL formatter:
package my.custom;
import org.hibernate.jdbc.util.BasicFormatterImpl;
import org.hibernate.jdbc.util.Formatter;
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
public class PrettySqlFormat implements MessageFormattingStrategy {
private final Formatter formatter = new BasicFormatterImpl();
#Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql) {
return formatter.format(sql);
}
}
There is no such option provided to achieve it via configuration only yet. I think you have 2 options here:
fill a new bug/feature request report (which could bring benefit to others using p6spy as well) on: https://github.com/p6spy/p6spy/issues?state=open or
provide custom implementation.
For the later option, I believe you could achieve it via your own class (depending on the logger you use, let's assume you use Log4jLogger).
Well, if you check relevant part of the Log4jLogger github as well as sourceforge version, your implementation should be rather straightforward:
spy.properties:
appender=com.EffectiveSQLLog4jLogger
Implementation itself could look like this:
package com;
import com.p6spy.engine.logging.appender.Log4jLogger;
public class EffectiveSQLLog4jLogger extends Log4jLogger {
public void logText(String text) {
super.logText(getEffectiveSQL(text));
}
private String getEffectiveSQL(String text) {
if (null == text) {
return null;
}
final int idx = text.lastIndexOf("|");
// non-perfect detection of the exception logged case
if (-1 == idx) {
return text;
}
return text.substring(idx + 1); // not sure about + 1, but check and see :)
}
}
Please note the implementation should cover github (new project home, no version released yet) as well as sourceforge (original project home, released 1.3 version).
Please note: I didn't test the proposal myself, but it could be a good starting point and from the code review itself I'd say it could work.
I agree with #boberj, we are used to having logs with Hibernate formatter, but don't forget about batching, that's why I suggest to use:
import com.p6spy.engine.spy.appender.MessageFormattingStrategy;
import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;
import org.hibernate.engine.jdbc.internal.Formatter;
/**
* Created by Igor Dmitriev on 1/3/16
*/
public class HibernateSqlFormatter implements MessageFormattingStrategy {
private final Formatter formatter = new BasicFormatterImpl();
#Override
public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql) {
if (sql.isEmpty()) {
return "";
}
String template = "Hibernate: %s %s {elapsed: %sms}";
String batch = "batch".equals(category) ? ((elapsed == 0) ? "add batch" : "execute batch") : "";
return String.format(template, batch, formatter.format(sql), elapsed);
}
}
In p6Spy 3.9 this can be achieved quite simply. In spy.properties set
customLogMessageFormat=%(effectiveSql)
You can patch com.p6spy.engine.spy.appender.SingleLineFormat.java
removing the prepared element and any reference to P6Util like so:
package com.p6spy.engine.spy.appender;
public class SingleLineFormat implements MessageFormattingStrategy {
#Override
public String formatMessage(final int connectionId, final String now, final long elapsed, final String category, final String prepared, final String sql) {
return now + "|" + elapsed + "|" + category + "|connection " + connectionId + "|" + sql;
}
}
Then compile just the file
javac com.p6spy.engine.spy.appender.SingleLineFormat.java
And replace the existing class file in p6spy.jar with the new one.

axis2 xsd:date format issue

Merged with axis2 xsd:date format issue.
In WSDL I have the following format:
USER_ACT_STRDT is a date.
When I generate the STUB (using Axis2 1.5.3), the generated stub (ADB Data Binding) has the following source code :
public void setUSER_ACT_STRDT_TypeDef(Date param) {
if (ConverterUtil.convertToString(param).matches("\d{4}-\d{2}-\d{2}")) {
this.localUSER_ACT_STRDT_TypeDef=param; } else { throw new java.lang.RuntimeException();
} }
This method always throws RuntimeException because the ConverterUtil.convertToString() method returns a String in a different format than "yyyy-mm-dd". It returns the date by appending +5.30 as 2011-03-21+05:30.
I tried passing the date in different formats but same result for all.
Can any one suggest how to resolve this issue.

AXIS 1.5.3 Date Formatting Issue

Merged with axis2 xsd:date format issue.
In WSDL I have the following format:
When I generate the STUB (using Axis2 1.5.3), the generated stub (ADB
Data Binding) has the following source code :
public void setUSER_ACT_STRDT_TypeDef(Date param)
{
if (ConverterUtil.convertToString(param).matches("\d{4}-\d{2}-\d{2}"))
{
this.localUSER_ACT_STRDT_TypeDef=param;
}
else
{
throw new java.lang.RuntimeException();
}
}
This method always throws RuntimeException because the
ConverterUtil.convertToString() method returns a String in a different
format than "yyyy-mm-dd".
It returns the date by appending +5.30 as 2011-03-21+05:30.