Subscribe To Our Newsletter
You will receive our latest post and tutorial.
Thank you for subscribing!

required
required


CompletableFuture

 

CompletableFuture is used for asynchronous or non-blocking programming in Java. With asynchronous programming, you can have one or many tasks being processed at the same time. This is done by using separate threads, other than the main thread, to process other tasks. The main thread is not blocked or waiting so tasks can be done in parallel. The main thread is just notified when other threads are done with their tasks whether it’s completion or failure.

A Future is used as a reference to the result of an asynchronous computation. It provides an isDone() method to check whether the computation is done or not, and a get() method to retrieve the result of the computation when it is done.

 

CompletableFuture<String> realName = restService.getName();
		
try {
	log.info("sleeping 1000 millseconds");
		
	TimeUnit.SECONDS.sleep(5);
	if (realName.isDone()) {
		log.info("yeah here is your realname={}", realName.get());
	}else {
		log.info("nah realname has not found yet");
	}
} catch (InterruptedException | ExecutionException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
}

 

 

 

		CompletableFuture<ArrayNode> plUsers = restService.getPlaceHolderTestingList(RestService.PLACEHOLDER_USER);
		
		CompletableFuture<ArrayNode> plTodos = restService.getPlaceHolderTestingList(RestService.PLACEHOLDER_TODO);
		
		CompletableFuture<ArrayNode> plComments = restService.getPlaceHolderTestingList(RestService.PLACEHOLDER_COMMENT);
		
		CompletableFuture<ArrayNode> plPhotos = restService.getPlaceHolderTestingList(RestService.PLACEHOLDER_PHOTO);
		
		CompletableFuture.allOf(plUsers,plTodos,plComments,plPhotos).join();
		
		try {
			log.info("plUsers={}",ObjectUtils.toJson(plUsers.get()));
			log.info("plTodos={}",ObjectUtils.toJson(plTodos.get()));
			log.info("plComments={}",ObjectUtils.toJson(plComments.get()));
			log.info("plPhotos={}",ObjectUtils.toJson(plPhotos.get()));
			
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

 

 

		List<String> placeHolders = Arrays.asList(RestService.PLACEHOLDER_USER, RestService.PLACEHOLDER_TODO);

		CompletableFuture<ArrayNode>[] futures = new CompletableFuture[placeHolders.size()];

		for (int i = 0; i < futures.length; i++) {
			CompletableFuture<ArrayNode> pl = restService.getPlaceHolderTestingList(placeHolders.get(i));
			futures[i] = pl;
		}

		CompletableFuture.allOf(futures).join();

		try {
			for (int i = 0; i < futures.length; i++) {
				ArrayNode plhds = futures[0].get();
				log.info("plhds={}", ObjectUtils.toJson(plhds));
			}

		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

 

September 24, 2019

Brain Teaser

September 23, 2019

AWS – Kubernetes on AWS

September 6, 2019

Spring Boot Thread Pool

 

One technique would be to balance thread pool size based on individual demand for hardware. However it might be important to give priority to web clients over requests coming in via JMS and therefore you might balance the pools in that direction. Of course as you rebalance you’ll have to adjust the size of each pool to take into account the difference in hardware demanded.

Getting a proper configuration for a thread pool may not be easy but it’s also not rocket science. The mathematics behind the problem are well understood and are fairly intuitive in that we meet them all the time in our every day lives. What is lacking are the measurements (as witness by j.u.c.ExecutorService) needed to make a reasonable choice. Getting to a proper setting will be a bit fiddly as this is more like bucket chemistry than a precise science but spending a little bit of time fiddling can save you the headache of having to deal with a system that has been destabilized by higher than expected workloads.

Here is a Thread Pool configuration sample.

/*
	 * corePoolSize parameter is the amount of core threads which will be
	 * instantiated and kept in the pool. If all core threads are busy and more
	 * tasks are submitted, then the pool is allowed to grow up to a
	 * maximumPoolSize.
	 */

	@Bean(name = "taskExecutor")
	public ThreadPoolTaskExecutor taskExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		// initial number of threads
		executor.setCorePoolSize(20);

		// max number of threads
		executor.setMaxPoolSize(Integer.MAX_VALUE);

		// some tasks may be put into a queue to wait for their turn.
		executor.setQueueCapacity(500);
		executor.setThreadNamePrefix("Auth-Thread-");
		executor.setAllowCoreThreadTimeOut(true);
		executor.setKeepAliveSeconds(60);
		executor.setWaitForTasksToCompleteOnShutdown(true);
		executor.setAwaitTerminationSeconds(60);
		executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
		executor.initialize();

		return executor;
	}

 

September 6, 2019

Spring Boot Security Config

Java Security Configuration 

Add dependency

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Add SecurityConfig class

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.RegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import com.folaukaveinga.security.CustomAcccessDeniedHandler;
import com.folaukaveinga.security.CustomAuthenticationFilter;
import com.folaukaveinga.security.CustomAuthenticationProvider;
import com.folaukaveinga.security.CustomLoginFilter;
import com.folaukaveinga.security.CustomLogoutHandler;
import com.folaukaveinga.security.CustomLogoutSuccessHandler;
import com.folaukaveinga.utils.PathConstantUtil;

/**
 * Configure Security
 * @author fkaveinga
 *
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider customAuthenticationProvider;
    
    @Autowired
    private CustomLogoutHandler customLogoutHandler;
    
    @Autowired
    private CustomLogoutSuccessHandler customLogoutSuccessHandler;
    
    @Autowired
    private CustomAcccessDeniedHandler customAcccessDeniedHandler;
    
    @Bean
    public CustomLoginFilter customUsernamePassworAuthenticationFilter() throws Exception {
        return new CustomLoginFilter(PathConstantUtil.LOGIN_URL,authenticationManagerBean());
    }
    
    @Bean
    public CustomAuthenticationFilter customAuthenticationFilter() {
        return new CustomAuthenticationFilter();
    }
    
    @Bean
    public RegistrationBean jwtAuthFilterRegister(CustomAuthenticationFilter customAuthenticationFilter) {
        FilterRegistrationBean<CustomAuthenticationFilter> registrationBean = new FilterRegistrationBean<CustomAuthenticationFilter>(
                customAuthenticationFilter);
        registrationBean.setEnabled(false);
        return registrationBean;
    }
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // rest call rules
        http
            .cors().and().csrf().disable()
            .authorizeRequests()
                .antMatchers(PathConstantUtil.PING_URL).permitAll()
                .antMatchers(PathConstantUtil.LOGIN_URL).permitAll()
                .antMatchers(PathConstantUtil.SIGNUP_URL).permitAll()
                .antMatchers(PathConstantUtil.PUBLIC_ENDPOINTS).permitAll()
                .anyRequest().permitAll();
                    
        // logout
        http.logout()
            .logoutRequestMatcher(new AntPathRequestMatcher(PathConstantUtil.LOGOUT_URL))
            .addLogoutHandler(customLogoutHandler)
            .logoutSuccessHandler(customLogoutSuccessHandler);
        
        // Login filter
        http.addFilterBefore(customUsernamePassworAuthenticationFilter(),UsernamePasswordAuthenticationFilter.class);
        // Signup filter
        http.addFilterBefore(customAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
        
        // stateless
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        
        // handler access denied calls
        http.exceptionHandling().accessDeniedHandler(customAcccessDeniedHandler);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.authenticationProvider(customAuthenticationProvider);
    }
    
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
            .antMatchers(PathConstantUtil.SIGNUP_URL)
            .antMatchers(PathConstantUtil.LOGIN_URL)
            .antMatchers(PathConstantUtil.PING_URL)
            .antMatchers(PathConstantUtil.AUTH_TOKEN_URL)
            .antMatchers(PathConstantUtil.SWAGGER_DOC_URLS)
            .antMatchers(PathConstantUtil.PUBLIC_ENDPOINTS)
            .antMatchers("/actuator/**");
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        return encoder;
    }
    
    @Bean
    public MethodInvokingFactoryBean methodInvokingFactoryBean() {
        MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
        methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
        methodInvokingFactoryBean.setTargetMethod("setStrategyName");
        methodInvokingFactoryBean.setArguments(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
        return methodInvokingFactoryBean;
    }
}

 

 

 

September 6, 2019