Tech Bites

Convert String into LocalDate

Convert String Into LocalDate

Code


   public static LocalDate parseDate(String date) {
        DateTimeFormatter formatter =
                 DateTimeFormatter.ofPattern("M/d/y");
        return LocalDate.parse(date,formatter);
    }

Unit Tests

    @Test
    public void testDateParsing() {
        String testDate;
        testDate ="01/01/2022";
        LocalDate expected = LocalDate.of(2022, 1, 1);
        assertEquals(expected, DateParser.parseDate(testDate));
    }

    @Test
    public void testDateParsingSingleDigitMonthAndYear() {
        String testDate;
        testDate = "1/1/2022";
        LocalDate expected = LocalDate.of(2022, 1, 1);
        assertEquals(expected, DateParser.parseDate(testDate));
    }

A "Simple" Change to a Web App

A "Simple" Change to a Web App

Imagine a basic web app (SPA, REST API, Sql database) with a new-user registration form. The form collects a first and last name of a new user. It is decided that the middle name needs to be collected on the form as well.

What changes need to be made to accomodate this?

  • The SQL table needs to have “middle_name” column added. Requires a DDL script.
  • The Java layer needs to update a USER entity to include middleName field. Java Change.
  • The REST API - if using a DTO, needs the DTO updated. Java Change.
  • The repository code, if implemented manually, needs to be updated. (Entity mapping can alleviate some changes). Java Change.
  • The UI needs to add a field in the form to collect the middle name, and likely modify the model stored in the UI. JavaScript/Typescript change.

Also unit tests need to be updated, flyway or liquidbase scripts, redeployments have to be scheduled (if the deployment pipeline is working). Checkstyles and test coverage re-ran.

Spring Batch: Restart A Failed Batch Job Using an API Endpoint

Spring Batch: Restart a Failed Batch Job Using an API Endpoint

An key thing to remember in Spring Batch is that an instance of a Spring Batch job can only be restarted if it FAILED. If the job completeds SUCCESSFULLY a new instance of the job will have to be created to run it again.

When restarting batch jobs manually, is helpful to create an API endpoint for restarting failed batch jobs.

When a batch job is run the first time, it is assigned a batch_job_instance_id and a batch_job_execution_id.

Create A Service In Angular

Create a Service in Angular

To create a service in Angular:

cd /src/app/directory_to_create_service
ng generate service lookup 

To use service in a component inject into the constructor.

constructor(private lookupService: LookupService);
someMethod() {
    return this.lookupService.lookSomethingUp();
}

Spring Batch: Chunk Size

Spring Batch: Chunk Size

In Spring Batch, when configuring a step you can set the chunk size.

This is a very critical and often overlooked settings.

When developing locally, it’s difficult to catch performance problems because typically local data sets are very small. However once deployed the performance problems can be crippling.

The chunk size determines how many records are processed before a commit is triggered.

So if your chunk size is set to 10 and you have 1 million records to process, the application will trigger 100,000 commits. This will be very slow.

Monitor Memory And CPU of a Pod in Rancher

Monitor Memory and CPU of a Pod in Rancher

If you have a kubernetes pod being terminated due to OOMKilled (Out of Memory Killed), you can monitor the memory usage of the pod during the action that is using too much memory.

  1. Workload -> Pods -> Find ther POD to monitor and click the name
  2. Click Metrics
  3. Set the range and refresh parameters (5s refresh during active monitoring)
  4. Run process (trigger it through an API call/Swagger endpoint)
  5. Monitor memory utilization during the process

Create Spring App and Deploy in 8 Steps

Create Spring App and Deploy in 8 Steps

To create a brand new spring boot app and deploy to a web server in 8 steps you can use the following:

Prerequisites

  • Install Heroku CLI
  • Install Spring CLI

Commands

heroku login
spring init --dependencies=web demo
cd demo
git init
git add .
git commit -m "new spring app"
heroku create
git push heroku master

Kubernetes Pod Dies Unexpectedly with No Error in Console Log

Kubernetes Pod Dies Unexpectedly With No Error in Console Log

If you have a container in kubernetes unexpectedly disconnect with no error in the console log you can check the pod yaml for the last state of the pod.

Go to your Pod -> (three dots) Edit Yaml -> scroll to status (at the bottom) -> expand.

From here you can see the last status such as:

reason: OOMKilled

Check Spring Profiles in Rancher

Check Spring Profiles in Rancher

Spring profiles can be used to toggle behaviors in a spring app. If your app is running in a container in Rancher (Kubernetes) you may need to see what spring profiles are being applied. To check what spring profiles a service is running in Rancher:

  • Click Workload in the navigation bar -> Pods
  • Search for your service and click on it
  • Click related resources
  • Click configMap
  • Scroll to SPRING_PROFILES_ACTIVE

Spring Batch: Running Batch Jobs Asynchronously

Spring Batch: Running Batch Jobs Asynchronously

When running multiple batch jobs in Spring Batch, the default JobLauncher waits to launch a job until the previous job running is COMPLETE. In order to run multiple batch jobs simultaneously, the JobLauncher must be configured to run jobs asynchronously.

Configure the async job launcher


public JobLauncher customJobLauncher(@Autowired final JobRepository jobRepository) {
    final SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
    jobLauncher.setJobRepository(jobRepository);

    // Here we configure the async task executer
    jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
    jobLauncher.afterPropertiesSet();
    return jobLauncher;
}

Run a job with the asyc job launcher

public class BatchJobScheduler {

    @Autowired
    private JobLauncher customJobLauncher;

    @Autowired
    private Job customJob;

    @Scheduled(cron="* * 1 * * *")
    public BatchStatus scheduleJob() {
        final JobExecution ex = customJobLauncher.runJob(customJob, getJobParameters());
        return ex.getStatus();
    }

    JobParameters getJobParameters() {
        // Get the job parameters
    }
}

Spring Batch: Limit How Frequent a Batch Job Runs

Spring Batch: Limit How Frequent a Batch Job Runs

Often in designing batch jobs you want to limit the frequency that a job can run. For example, if you want a batch job to run once a day, you can use @Scheduled annotation to run the batch job once a day. This is enough if you only run one instance of the batch program and there are no other ways to launch the job.

But if you have manual ways to launch the same job, or you are you using kubernetes to run multiple instances of your batch program, the batch job may be attempted to run multiple times in one day, even if you intend to only run once a day.

Spring Batch: Sharing Batch Step Configurations

Spring Batch: Sharing Batch Step Configurations

When defining a Spring batch step, often common configurations are added to almost every step. In order to not violate DRY (Don’t Repeat Yourself), a StepBuilder can be customized upstream with all the shared configurations.

Configuring the StepBuilder


@Configuration
public class SharedStepBuilderFactory extends StepBuilderFactory {

    @Autowired
    public JobRepository jobRepository;

    @Autowired
    public PlatformTransactionManager transactionManager;

    // Inject shared values here and use them as well
    @Value
    private String logDirectory;

    public SharedStepBuilderFactory(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        super(jobRepository, transactionManager);
    }

    @Override
    public StepBuilder get(final String name) {
        // Get the default step builder
        final StepBuilder builder = super.get(name);

        // Add listeners you want for EVERY step
        stepBuilder.listener(new StepLoggingListener());
        stepBuilder.listener(getCustomLoggingListener(logDirectory);
        return stepBuilder;
        }
}

Implementation

@Configuration
public class StepConfig {

    @Bean
    public Step getStepOne(final SharedStepBuilderFactory sharedStepBuilderFactory) {
        return sharedStepBuilderFactory
        .get("stepOne") 
        .reader(stepOneReader())
        .writer(stepOneWriter())
        .build(); // The listeners are already configured for this step from the SharedStepBuilderFactory
    }
}

Java Tip: Method Reference

Java Tip: Method Reference

Instead of

for(String name: names) {
	System.out.println(name);
}

Do

// This is called a method reference
names.foreach(System.out::println);