Friday, June 26, 2020

Design Patterns Wrapper revisited

 Now lots of software designed and developed following microservice architecture. Components need to communicate with each other via VO (value objects) and DTO (data transfer objects) as JSON string.

A new problem for the shared model occurs.

1. Typical approach is about to keep them following anemic model approach. Like a property holders. Usually as shared library.
2. That means very soon classes are widely used and modify them can requires huge effort. Pure design hard to improve after it is used in many places.
3. For some microservices some query methods (or even model mutations) are needed and somewhere not.

Consider this case.
We have the VO designed as:


1
2
3
4
5
6
7
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PriceVO {
    private String currencyCode;
    private Long amount;
}

which is used across the components.

As we can see it looks pretty ugly and anemic, no immutability and without operations.
1. No immutability - any code which receives can modify it at any step of invocation
2. This class structure has no sense, this presents Money object, like a 100$ note f.e. Does it make sense if amount is null or currencyCode is also null? It is like 100 of unknown currency or unknown amount of dollars. 
3. Maybe null amount is considered as zero? Or currency code "USD" or "usd" should be considered as same and correct values? What if null currency code must be considered as default currency?
4. Very probably it would be nice to add or deduct money. Changing currency has no sense at the scope of this object but different other ops would be nice to have.
5. What's about the currency? Is it a dictionary?

How we can try to fix or eliminate these problems?

First we can change the VO itself, to add immutability or make model (amount or currency) more strict. But is it easy effort? To change and then update artifact deps in many places? And then test it.

A better solution is to use Wrapper pattern. Or any approach which looks like Wrapper. Try to improve it: model, add ops. Better API.

Okay, second variant looks better but how and where we can put this logic? Like a new helper or a service? From my point of view we can develop POJO with ops and following naming convention. Good name could be PriceVOOps.

First let's take care about the code, make it dictionary. If absence is not defined and must be considered as default value the solution could be put this check in the custom restore method (restore Enum constant by the String raw value).

1
2
3
4
// #3
public enum CurrencyCode {
    USD, EUR
}


And then develop operations and class, fixing all the mentioned concerns


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package wkda.api.retail.util;

import CurrencyCode;
import PriceVO;

import java.util.Optional;
import java.util.function.Supplier;

import static java.util.Objects.requireNonNull;


public class PriceVOOps {
    private long price;
    private CurrencyCode currencyCode;

    private PriceOps() {
    }

    // #1 immutability
    // #2 null safety, strict model, enum constant
    private PriceVOOps(long price, CurrencyCode currencyCode) {
        this.price = price;
        this.currencyCode = currencyCode;
    }

    // finally get improved value
    public PriceVO get() {
        return new PriceVO(currencyCode.name(), price);
    }

    //
    // factory method
    //
    public static PriceVOOps zero(String currencyCode) {
        // implicit not null check
        return new PriceVOOps(0, CurrencyCode.valueOf(currencyCode.toUpperCase()));
    }
    // #5
    public static PriceVOOps from(PriceDTO priceDTO) {
        return new PriceVOOps(
                amountOrZero(priceDTO.getAmountMinorUnits()),
                CurrencyCode.valueOf(priceDTO.getCurrencyCode().toUpperCase())
        );
    }

    public static PriceVOOps from(Supplier<String> currencyCodeSupplier, Supplier<Long> priceSupplier) {
        return new PriceVOOps(
                amountOrZero(priceSupplier.get()),
                CurrencyCode.valueOf(currencyCodeSupplier.get().toUpperCase())
        );
    }

    // #4
    // Ops, add more if needed
    //
    public PriceVOOps deduct(PriceVOOps priceVOOps) {
        if(priceOps.currencyCode != currencyCode) {
             throw new IllegalArgumentException("Operations must be with the same currency: " + priceOps);
        }

        return new PriceVOOps(price - priceOps.price, priceOps.currencyCode);
    }

    // internal helpers
    private static Long amountOrZero(Long amountMinorUnits) {
        return Optional.ofNullable(amountMinorUnits).orElse(0L);
    }
}

Saturday, May 12, 2018

Spring Boot explained simply


Why Spring Boot

Spring Boot gives us a new level of abstraction in the server software building. As for the Spring Framework version 2.x and less the main building block was a bean. Or a class in other words. Which was declared in the XML application context file. And the most popular approach was layered architecture: they were grouped by functional roles like persistence, integration, services, DAOs, etc.

With time programs became more and more complex and starting from the version of 2.5 a new feature like component scanning was introduced in Spring. And thus new building block of the program became a package. One package - one feature. And at the same time developers still required to develop and configure some infrastructure code like Dispatcher Servlet, typical Jackson configuration and etc.

At the current time of software complexity we can manage tens and hundreds of microservices in one product, and typical building block is the Microservice or and application typically deployed on a separate JVM. So the Spring Boot is intended to give the developers nice tool to solve this problem. And at the same time is brings a lot of pre-configured functionality mainly responsible for the same infrastructure things described above.

What is Spring Boot

1. This is a lots infrastructure things included and configured by default.

By default configured Dispatcher Servlet for the web app, Jackson mapper, logging, Spring MVC config is created and preconfigured using default settings, etc.

2. These standard infrastructure configs and beans are simply configured or customized by text files.

For example see how simply configured by default Jackson Object Mapper could be customized by text file:  https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-customize-the-jackson-objectmapper

3. Frameworks integrations. They are recognized by the availability in the classpath. Auto-configurations.

Web servers like Jetty or Tomcat, MongoDB client and connections, Cassandra and others

4. Ready to use infrastructure to monitor the application. Spring Boot Actuator framework.

5. Additional Spring framework improvements like set of @Conditional* annotations and property holders (mapping text props to the POJO)

All these features allow developer spend less time on the standard things and configurations and stay focused on the business features development. Get ready boilerplate apps or the templates in one minute.

That's it about Spring Boot in two words to get the main idea and start creating your app from here: http://start.spring.io.

Saturday, December 30, 2017

GWT and Spring MVC

In this post I'd like to share the code I developed in May of 2011 when started to work with GWT.

The first thing I did not like was the way how it integrated with the server side. The typical usage of server is to work with it through the RPC using the Servlets. Ok good, but what if I use another technology built a top of Servlets? SparkJava, Spring MVC, whatever? Any framework which follows the Front Controller / MVC paradigm.

Check these resources to get know on which patterns Spring MVC is built around:
https://martinfowler.com/eaaCatalog/frontController.html, https://martinfowler.com/eaaCatalog/applicationController.html, https://martinfowler.com/eaaCatalog/pageController.html).

It violates these principles since I need to add some Servlets responsible for the RPC somewhere aside. For example what if I need to get current Locale or cover with Filter security (f.e. Spring Security) in the code of that Servlets? For the Spring MVC Controller I have it all out of the box. Also I do not like mixing Servlet code which is infrastructure code with the logical/business code: when I need to create the RPC endpoint I need to extend the com.google.gwt.user.server.rpc.RemoteServiceServlet class which is servlet and put the business code there.

To solve these problems I developed very elegant integration with Spring MVC (Spring Framework) where you as the developer can focus on business and forget about the infrastructure and utilize all the power of Spring Framework.

Here it is: https://github.com/deventh/gwt.rpc.springmvc. This is upgraded version of the previous version: https://github.com/deventh/gwtrpcspringmvc with some changes: GWT RequestFactory approach is dropped and Async. Servlet 3.0 approach is added. So the performance is must be better now due no blocking nature. Find the framework and examples how to use there.

So now just forget about the Servlets stuff and start to build the software in the Spring way. The Eclipse IDE GWT plugin generates sample demo application with the greeting service (http://www.gwtproject.org/doc/latest/tutorial/create.html) as the demo project. Lets change it using my framework. How it will look like?

Client service looks the same

package com.github.deventh.gwt.rpc.springmvc.application.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("greet/greetingService.gwt")
public interface GreetingService extends RemoteService {
 String greetServer(String name);
}

But it implementation looks different: no need to extend the Servlet anymore and somehow get the reference to the current Spring Context and extract beans form there. So here it is:


package com.github.deventh.gwt.rpc.springmvc.application.server;

import com.github.deventh.gwt.rpc.springmvc.application.client.AnotherService;
import com.github.deventh.gwt.rpc.springmvc.application.client.GreetingService;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;

@Service("greetingService")
public class GreetingServiceImpl implements GreetingService, AnotherService {
 @Override
 public String greetServer(String name) throws IllegalArgumentException {
  return MessageFormat.format("Hello, {0}!", name);
 }
}

How this Remote Service is published and how it takes care about the serving the request - this is what this framework does. Even more as I mentioned above the server performance (capacity) is better due it async. nature. It is built using Java 8, Servlet 3.0 and Spring Framework 4.x. If you need downgrade in some technologies - try to use prev. version or make the modifications you need.

In this repo you can find some examples how to use it. You can also define the the way Application Exceptions are mapped to the client Exceptions and how to sue it with the Spring Security for some situations like session is expired.

Just a few works about how it is working under the hood. The new Handler mapping is registered which is responsible for the serving requests. It uses the  in the com.google.gwt.user.server.rpc.RemoteServiceServlet async way if allowed. But before that is scans for all the available Spring Beans which extend the Remote Service.

So that's is, develop nice apps with the cool logic using GWT and forget about the infrastructure!



Sunday, July 23, 2017

Spring MVC RequestBodyAdvice or how to add a processing step for parameters in Page Controller methods

... There are a few problems when we need to add some additional processing steps for the Spring MVC Page Controller method parameters. Before the Spring 4.2 we needed to add additional Argument Resolver to do that which was a bit problematic if we need to mix our logic with standard Spring MVC existing one like declarative validation using @Valid annotation?

Assume we have the most popular Request Mapping approach (@Controller/@RequestMapping) and want to add some logic deal with with incoming parameters. It could be the problem of HTML-escaping (JavaScript, XML, SQL, whatever) of some fields for incoming POJOs (DTOs).

Here is the Controller code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.example.demo;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;

@Controller
public class ReportController {
    @GetMapping(value = "/content")
    void report(@RequestBody @Valid ContentRequest contentRequest) {
        // process it ...
    }

    @JsonTypeName("content")
     static class ContentRequest {
        @JsonProperty("id")
        long id;

        @JsonProperty("title")
        @Length(max = 10000, message = "{validation.max.length.exceeds}")
        @NotBlank(message = "{validation.not.empty}")
        String content;
    }
}

And we need to add HTML escape for the content field since it could be published somewhere on other pages.

The solution might be to start using RequestBodyAdvice feature available since Spring MVC.

Let's declare our Advice to MVC configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@Configuration
@EnableWebMvc
class MvcConfig extends WebMvcConfigurationSupport {
 @Resource
 private RequestBodyAdvice escapeRequestBodyAdvice;

 @Override
 protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
  // we can avoid adding new custom since we can use RequestBodyAdvices ...
 }

 @Override
 public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
  RequestMappingHandlerAdapter requestMappingHandlerAdapter = super.requestMappingHandlerAdapter();
  // here is the our custom one: escapeRequestBodyAdvice
  requestMappingHandlerAdapter.setRequestBodyAdvice(Collections.singletonList(escapeRequestBodyAdvice));
  return requestMappingHandlerAdapter;
 }
}

and our RequestBodyAdvice looks like:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Component
public class EscapeRequestBodyAdvice extends RequestBodyAdviceAdapter {
    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        EscapeBeanUtil.escape(body);
        return body;
    }
}

where EscapeBeanUtil is the utility to escape the fields. It is not recursive - just for the demo purposes. It searches for @EscapeHTML and escapes the annotated field.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.util.ReflectionUtils;

class EscapeBeanUtil {
  /**
   * Only one level of simple String fields supported
   *
   * @param bean
   */
  static void escape(Object bean) {
    ReflectionUtils.doWithFields(
        bean.getClass(),
        field -> {
          if (!field.isAccessible()) {
            field.setAccessible(true);
          }

          Object value = ReflectionUtils.getField(field, bean);

          if (value != null) {
            String escaped = StringEscapeUtils.escapeHtml4(
                String.valueOf(value)
            );

            ReflectionUtils.setField(field, bean, escaped);
          }
        },
        field -> field.getAnnotationsByType(EscapeHTML.class).length > 0 &&
            String.class.isAssignableFrom(field.getType())
    );
  }
}

Annotation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface EscapeHTML {

}


Now, after these changes we have our POJO/DTO a bit modified (See at @EscapeHTML)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;

@Controller
public class ReportController {
    @GetMapping(value = "/content")
    void report(@RequestBody @Valid ContentRequest contentRequest) {
        // process it
    }

    @JsonTypeName("content")
     static class ContentRequest {
        @JsonProperty("id") // other fields which require validation...
        long id;

        @JsonProperty("title")
        @Length(max = 100000, message = "{validation.max.length.exceeds}")
        @NotBlank(message = "{validation.not.empty}")
        @EscapeHTML
        String content;
    }
}

That's it!

Also please note that now validation is broken a bit: after HTML escaping limits for the content length could not fit since more chars are added. To overcome it you can pre-calculate the field size on UI or relax a bit the size or add some custom validator for that field. But very often for the big text inputs where the escape is required there are no limits


Wednesday, June 28, 2017

Spring Security Custom Authentication Filter

In this post I'd like to share how to write own custom Filter in Spring Security framework to authenticate. If you have your web application built using this security framework this post might be useful  for you.

Well it is very often needed allow user login into the application on the fly without any input forms. For example by link from the email or SMS, by some header in the REST API etc. I take the letter as an example wehere there this the link with parameter:

Hi, dear user!
There is a new comment on your page.
See all the activity in your profile.

And the activity link href is:
http://example.com/activity.htm?token=25390bd438e1f17bee7b0d320a62707f

And your system must be able to authenticate the user just having this token: 25390bd438e1f17bee7b0d320a62707f

First of all you need to know how to restore the user info by this token value and vice versa: you know how to generate this token matching the user info.
The simplest solution is to store them in database providing the expiration info and other checks if needed.

Now we need to write the Filter to find this token in request:

Filter:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;

import javax.servlet.http.HttpServletRequest;

public class TokenFilter extends AbstractPreAuthenticatedProcessingFilter {
  static final String TOKEN_PARAMETER = "token";

  @Override
  protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
    return request.getHeader(TOKEN_PARAMETER);
  }

  @Override
  protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
    return request.getHeader(TOKEN_PARAMETER);
  }
}

Now let's configure the framework: register the filter and code to authenticate.

In Spring Security there is the possibility to provide additional fallback code to provide the user authentication when primary one is failing using user details service. Sample config where we register our filter and authentication manager might look like:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;


import javax.annotation.Resource;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Resource
  private UserDetailsService userDetailsService;
  /*
  Fallback authentication mananger
  */
  @Resource
  private TokenAuthenticationManager tokenAuthenticationManager;

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.parentAuthenticationManager(tokenAuthenticationManager);
    auth.userDetailsService(userDetailsService);
  }

  @Override
  public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/assets/**");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    /*
    This our FILTER
    */
    TokenFilter filter = new TokenFilter();
    filter.setAuthenticationManager(authenticationManager());
    http.addFilterBefore(filter, AbstractPreAuthenticatedProcessingFilter.class);

    http.logout().logoutUrl("/auth/doLogout").logoutSuccessUrl("/auth/login.htm");
    http.rememberMe();
    http.authorizeRequests()
        .antMatchers("/reports/**/*").hasAnyAuthority(new String[]{"ADMIN", "USER"})
        .anyRequest().permitAll()
        .and()
        .formLogin()
        .usernameParameter("username")
        .passwordParameter("password")
        .loginPage("/pages/login.htm")
        .failureUrl("/pages/failure.htm")
        .defaultSuccessUrl("/index.htm")
        .loginProcessingUrl("/auth/doLogin")
        .permitAll();
  }
}

Now lets write this fallback authentication manager:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;

@Component
public class TokenAuthenticationManager implements AuthenticationManager {
  @Resource
  private TokenService tokenService;

  @Override
  public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    if (!(authentication instanceof PreAuthenticatedAuthenticationToken)) {
      throw new BadCredentialsException("Not supported auth");
    }

    final Object principal = authentication.getPrincipal();
    final Object creds = authentication.getCredentials();

    checkFilterProcessed(principal, creds);

    try {
      Token token = tokenService.getByValue(principal.toString());

      if (/* check token is valid: exists, not expired, etc */ false) {
        throw new BadCredentialsException("Bad token");
      }

      User user = tokenService.restoreUserByToken(token); 
      // User implements org.springframework.security.core.userdetails.UserDetails

      UsernamePasswordAuthenticationToken result =
          new UsernamePasswordAuthenticationToken(user, creds, user.getAuthorities());
      result.setDetails(user);
      return result;
    } catch (TokenNotFoundException e) {
      throw new BadCredentialsException(e.getMessage());
    }
  }

  private void checkFilterProcessed(Object principal, Object creds) {
    if (!Objects.equals(principal, creds)) {
      throw new BadCredentialsException("Not supported auth");
    }
  }
}


That's it!
This filter will be invoked only once when user is not logged out.
If you need to logout already authenticated user in the system - you need to create new Filter checking this token and insert it after the standard logout filter same as I did for TokenFilter and logout existing. See all available in org.springframework.security.config.annotation.web.builders.FilterComparator#FilterComparator.

For the case when you have REST API with a header you can modify token filter to extract the token, f.e. get it from the header with Authentication name

Design Patterns Wrapper revisited

 Now lots of software designed and developed following microservice architecture. Components need to communicate with each other via VO (val...