When writing a custom serialization, what is the difference between using SerializerProvider or jsonGenerator to generate the json - spring

I was trying to write a custom implementation for serializing an object like explained in here: Jackson custom serialization
Where I have:
#Override
public void serialize(
Item value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeNumberField("id", value.id);
...
}
But, I noticed that I could also use the SerializerProvider to write the same thing in this other way:
#Override
public void serialize(
Item value, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException {
jgen.writeStartObject();
provider.defaultSerializeField("id", value.id, jsonGenerator);
...
}
So I was wondering: what is the difference between:
jgen.writeNumberField("id", value.id);
and
provider.defaultSerializeField("id", value.id, jsonGenerator);

Related

Spring-boot BASIC Authentication not working in IE browser

I have done basic authentication using springboot with BasicAuthenticationEntryPoint and custom filter. It working as expected in Chrome but not working in IE browser.
First its prompting login page if entered wrong credentials then if we reload the page and its trying to authenticate with previous details only and not prompting login page again in IE browser but this same was working in chrome as expected.
Code as below:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().fullyAuthenticated().and().httpBasic()
.authenticationEntryPoint(new MyBasicAuthenticationEntryPoint());
http.addFilterAt(getCustomAuthenticationFilter(), BasicAuthenticationFilter.class);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
BasicAuthenticationEntryPoint code:
public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
org.springframework.security.core.AuthenticationException authException)
throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "Basic");
response.getOutputStream().println(authException.getMessage());
}
#Override
public void afterPropertiesSet() throws Exception {
setRealmName("localhost");
super.afterPropertiesSet();
}
}
CustomFilter Code:
public class CustomAuthenticationFilter extends BasicAuthenticationFilter {
#Autowired
AuthUsersService authUsersService;
#Autowired
public CustomAuthenticationFilter(AuthenticationManager authenticationManager) {
super(authenticationManager);
}
#Override
protected void onSuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
Authentication authResult) throws IOException {
System.out.println("Successful");
return;
}
#Override
protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException {
System.out.println("UN-Successful");
return;
}
}
Can anyone please suggest on this why above code not working on IE browser ?

Keep trailing zeros in bigdecimal in json

I have created onse serializer class which should restrict Bigdecimal to tow digits after decimal. But its removing zeros too. For ex: if value is 95.50, its truncating zero and output as 95.5 in json.
public class PriceJsonSerializer extends JsonSerializer {
#Override
public void serialize(BigDecimal value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException
{
jgen.writeNumber(value.setScale(2,
BigDecimal.ROUND_HALF_UP).toString());
}
}
To force the serializer to preserve your rounding without writing the value as a string, try "writeRawValue".
public class PriceJsonSerializer extends JsonSerializer {
#Override
public void serialize(BigDecimal value, JsonGenerator jgen,
SerializerProvider provider) throws IOException, JsonProcessingException
{
jgen.writeRawValue(value.setScale(2,
BigDecimal.ROUND_HALF_UP).toString());
}
}

Avoid part-r-00***** from appending in the end of MapReduce job output file

I am running a MR code using Multioutputformat class. part**** is getting appended in the end of my output file. How can i avoid that?
public class MR_reducer extends
Reducer {
private MultipleOutputs multipleOutputs;
#Override
protected void setup(Context context) throws IOException,
InterruptedException {
multipleOutputs = new MultipleOutputs(context);
}
#Override
protected void reduce(Text key, Iterable<Text> values, Context context)
throws IOException, InterruptedException {
for (Text value : values) {
multipleOutputs.write(value, new Text(""), key.toString());
}
}
#Override
protected void cleanup(Context context) throws IOException,
InterruptedException {
multipleOutputs.close();
}
}
This code snippet is working from me. You have few differences:
public static class Reduce extends Reducer<Text, Text, NullWritable, Text> {
private MultipleOutputs<NullWritable, Text> multipleOutputs;
protected void setup(Context context) throws IOException, InterruptedException {
multipleOutputs = new MultipleOutputs<NullWritable, Text>(context);
}
public void reduce(Text key, Iterable<Text> values, Context output) throws IOException, InterruptedException {
while (values.iterator().hasNext()) {
multipleOutputs.write(NullWritable.get(), values.iterator().next(), key.toString());
}
}
protected void cleanup(Context context) throws IOException, InterruptedException {
multipleOutputs.close();
}
}

PreAuthorize error handling

I'm using Spring Oauth2 and Spring Pre-post Annotations With Spring-boot
I Have a service class MyService. one of MyService methods is:
#PreAuthorize("#id.equals(authentication.principal.id)")
public SomeResponse getExampleResponse(String id){...}
can i control in some manner the json that is returned by the caller Controller?
the json that is returned by default is:
{error : "access_denied" , error_message: ".."}
I Want to be able to control the error_message param. I'm looking for something similar to:
#PreAuthorize(value ="#id.equals(authentication.principal.id)", onError ="throw new SomeException("bad params")")
public SomeResponse getExampleResponse(String id){...}
One way i thought of doing it is by Using ExceptionHandler
#ExceptionHandler(AccessDeniedException.class)
public Response handleAccessDeniedException(Exception ex, HttpServletRequest request){
...
}
but i can't control the message of the exception. and also i can't be sure that this Exception will be thrown in future releases
Spring Boot docs on error handling: http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-error-handling. One way you can control the JSON is by adding a #Bean of type ErrorAttributes.
#Bean
ErrorAttributes errorAttributes() {
return new MyErrorAttributes();
}
Implement AccessDeniedHandler
#Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
try {
ObjectMapper mapper = new ObjectMapper();
SomeJsonModel jsonResponse =new SomeJsonModel();
mapper.writeValue(response.getOutputStream(), jsonResponse);
} catch (Exception e) {
throw new ServletException();
}
}
SomeJsonModel will be your own POJO/model class which you can control
And add that access denied handler in Resource Server Configuration
#Override
public void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers(SECURED_PATTERN).and().authorizeRequests()
.antMatchers(HttpMethod.POST,SECURED_PATTERN).access(SECURED_WRITE_SCOPE)
.anyRequest().access(SECURED_READ_SCOPE).and()
.exceptionHandling().authenticationEntryPoint(newAuthExceptionEntryPoint())
.accessDeniedHandler(new MyAccessDeniedHandler());
}
It was not working for me when I implemented AccessDeniedHandler. So I created a ExceptionHandler function inside AuthenticationEntryPoint and marked the class as
#ControllerAdvice.
Please find the code below
#ControllerAdvice
#Component
public class EmrExceptionHandler implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(EmrExceptionHandler.class);
#Override
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AuthenticationException authException) throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_AUTHORIZED)));
}
#ExceptionHandler(value = {AccessDeniedException.class})
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,
AccessDeniedException accessDeniedException) throws IOException {
logger.error("AccessDenied error: {}", accessDeniedException.getMessage());
httpServletResponse.setStatus(HttpStatus.FORBIDDEN.value());
httpServletResponse.getWriter().write(convertObjectToJson(new ErrorResponse(ResponseMessages.NOT_PERMITTED)));
}
public String convertObjectToJson(Object object) throws JsonProcessingException {
if (object == null) {
return null;
}
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}

Old API to New API

My Original Question
since only feasible ans to that question is found in This Question
And the answer is in old API . So that force me to put a stupid question of translating these line to New API :
private long mapperCounter;
#Override
public void configure(JobConf conf) {
JobClient client = new JobClient(conf);
RunningJob parentJob =
client.getJob(JobID.forName( conf.get("mapred.job.id") ));
mapperCounter = parentJob.getCounters().getCounter(MAP_COUNTER_NAME);
}
Note : I want this code in reducer so inherited functions available are :
#Override
protected void setup(Context context) throws IOException,
InterruptedException {
}
#Override
protected void cleanup(Context context) throws IOException,
InterruptedException {
}
#Override
public void run(Context context) throws IOException,
InterruptedException {
Job job=new Job(context.getConfiguration());
}
#Override
public void reduce(ImmutableBytesWritable key,Iterable<ImmutableBytesWritable> result,Context context )
{
}
Thanks :) :)
This presentation summarizes the changes between the old and new API.

Resources