After I updated IntelliJ, it showed error message as bellows:
Plugin "Lombok" is incompatible with the newest IntelliJ
How-To
1. Uninstall Lombok plugin
2. Reinstall Lombok plugin
3. Restart IntelliJ
Plugin "Lombok" is incompatible with the newest IntelliJ
package com.test.tool.filegenerator.ftl.cp937; import com.test.tool.filegenerator.util.Cp973FileUtils; import lombok.extern.slf4j.Slf4j; import org.assertj.core.api.Assertions; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; @Slf4j @RunWith(SpringRunner.class) @SpringBootTest @ActiveProfiles("office") public class TS0110_050110_70118_R01FileTest { @Autowired private Cp973FileUtils cp973FileUtils; @ParameterizedTest @ValueSource(strings = {"delivery/test data/LN3112P2.LN3112P2"}) public void testReadTS0110_050110_70118_R01(String file) { Assertions.assertThatCode( () -> cp973FileUtils.readAndPrintContent(file)).doesNotThrowAnyException(); } }
package com.cht.tool.filegenerator.service; import java.io.IOException; public interface DownloadService { void downloadExcel() throws IOException; }
package com.cht.tool.filegenerator.service; import lombok.extern.slf4j.Slf4j; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; @Slf4j @Service @Profile({"default"}) public class JSoupDefaultService implements DownloadService { @Value("${jsoup.from}") private String from; @Value("${jsoup.to}") private String to; public void downloadExcel() throws IOException { log.debug("default profile"); Connection.Response response = null; try { response = Jsoup.connect(from) .ignoreContentType(true) .execute(); } catch (IOException e) { throw new IOException("fail to connect to google drive, error : " + e.getMessage(), e); } log.debug("status code = {}", response.statusCode()); Files.write(Paths.get(to), response.bodyAsBytes()); log.debug("excel file downloaded."); } }
package com.cht.tool.filegenerator.service; import lombok.extern.slf4j.Slf4j; import org.jsoup.Connection; import org.jsoup.Jsoup; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; @Slf4j @Service @Profile("office") public class JSoupService implements DownloadService { @Value("${jsoup.from}") private String from; @Value("${jsoup.to}") private String to; @Value("${jsoup.proxy}") private String proxy; @Value("${jsoup.port}") private int port; public void downloadExcel() throws IOException { log.debug("office profile"); Connection.Response response = null; try { response = Jsoup.connect(from) .proxy(proxy, port) .ignoreContentType(true) .execute(); } catch (IOException e) { throw new IOException("fail to connect to google drive, error : " + e.getMessage(), e); } log.debug("status code = {}", response.statusCode()); Files.write(Paths.get(to), response.bodyAsBytes()); log.debug("excel file downloaded."); } }
spring: profiles: active: default
package com.cht.tool.filegenerator; import com.cht.tool.filegenerator.service.DownloadService; import com.cht.tool.filegenerator.service.FileGeneratorService; import com.cht.tool.filegenerator.service.JSoupService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableAsync; import java.nio.file.Files; import java.nio.file.Paths; @Slf4j @SpringBootApplication public class FileGeneratorApplication { @Value("${jsoup.to}") private String to; public static void main(String[] args) { SpringApplication.run(FileGeneratorApplication.class, args); } @Bean CommandLineRunner run(FileGeneratorService fileGeneratorService, DownloadService downloadService) { return args -> { if (Files.exists(Paths.get(to))) { Files.delete(Paths.get(to)); } downloadService.downloadExcel(); fileGeneratorService.writePropertyFile(); fileGeneratorService.writeFtpPropertyFile(); fileGeneratorService.writeFtlFile(); fileGeneratorService.writeSqlFile(); }; } }
2020-07-24 11:18:50.529 DEBUG 6628 --- [ main] c.c.t.f.FileGeneratorApplication : Running with Spring Boot v2.3.1.RELEASE, Spring v5.2.7.RELEASE 2020-07-24 11:18:50.529 INFO 6628 --- [ main] c.c.t.f.FileGeneratorApplication : The following profiles are active: default 2020-07-24 11:18:51.328 INFO 6628 --- [ main] c.c.t.f.FileGeneratorApplication : Started FileGeneratorApplication in 1.355 seconds (JVM running for 2.489) 2020-07-24 11:18:51.343 DEBUG 6628 --- [ main] c.c.t.f.service.JSoupDefaultService : default profile 2020-07-24 11:18:53.501 DEBUG 6628 --- [ main] c.c.t.f.service.JSoupDefaultService : status code = 200 2020-07-24 11:18:53.732 DEBUG 6628 --- [ main] c.c.t.f.service.JSoupDefaultService : excel file downloaded.
package com.cht.tool.filegenerator.ftl.custom; import freemarker.core.Environment; import freemarker.core.TemplateDateFormat; import freemarker.core.TemplateDateFormatFactory; import freemarker.core.TemplateFormatUtil; import freemarker.core.TemplateValueFormatException; import freemarker.core.UnparsableValueException; import freemarker.template.TemplateDateModel; import freemarker.template.TemplateModelException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /** * 將西元年轉為民國年 * <p> * 使用方式 ${aDate?string.@mingguo}, 會將 2020/07/16 轉為 109/07/16 */ public class MingGuoTemplateDateFormatFactory extends TemplateDateFormatFactory { public static final MingGuoTemplateDateFormatFactory INSTANCE = new MingGuoTemplateDateFormatFactory(); private MingGuoTemplateDateFormatFactory() { // Defined to decrease visibility } @Override public TemplateDateFormat get(String s, int i, Locale locale, TimeZone timeZone, boolean b, Environment environment) throws TemplateValueFormatException { TemplateFormatUtil.checkHasNoParameters(s); return MingGuoTemplateDateFormat.INSTANCE; } private static class MingGuoTemplateDateFormat extends TemplateDateFormat { public static final MingGuoTemplateDateFormat INSTANCE = new MingGuoTemplateDateFormat(); private MingGuoTemplateDateFormat() { // Defined to decrease visibility } @Override public String formatToPlainText(TemplateDateModel templateDateModel) throws TemplateModelException { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd"); Date date = new Date(TemplateFormatUtil.getNonNullDate(templateDateModel).getTime()); String dateStr = dateFormat.format(date); return (Integer.parseInt(dateStr.substring(0, 4)) - 1911) + dateStr.substring(4); } @Override public Object parse(String s, int i) throws TemplateValueFormatException { try { return new Date(Long.parseLong(s)); } catch (NumberFormatException e) { throw new UnparsableValueException("Malformed long"); } } @Override public boolean isLocaleBound() { return false; } @Override public boolean isTimeZoneBound() { return false; } @Override public String getDescription() { return "西元年轉民國年"; } } }
Configuration cfg = new Configuration(Configuration.getVersion()); cfg.setClassForTemplateLoading(this.getClass(), "/"); // register the "mingguo" format: Map<String, TemplateDateFormatFactory> customDateFormats = new HashMap<>(); customDateFormats.put("mingguo", MingGuoTemplateDateFormatFactory.INSTANCE); cfg.setCustomDateFormats(customDateFormats);
<#-- 取得現在時間 --> <#assign aDateTime = .now> <#-- 只保留日期 --> <#assign aDate = aDateTime?date> <#-- create the macro variable: --> <#macro printDate mingguodate> 列印日期:${mingguodate} </#macro> <#macro footer records amount> ${"-"?right_pad(25, "-")} 總筆數:${records} 總金額:${amount} </#macro> <#-- call the macro: --> <@printDate mingguodate="${aDate?string.@mingguo}" /> <#assign total = 0> ${"水果名稱"?right_pad(10)}${"單價"?right_pad(10)}${"訂購數量"?right_pad(10)} ${"-"?right_pad(25, "-")} <#list rows as row> <#assign total += row.price * row.quantity> ${row.name?right_pad(10)}${row.price?string.@ntd?left_pad(10)}${row.quantity?left_pad(10)} </#list> <#-- call the macro: --> <@footer records="${rows?size?left_pad(10)}" amount="${total?string.@ntd?left_pad(10)}" />
package com.cht.tool.filegenerator.ftl.custom; import freemarker.core.Environment; import freemarker.core.TemplateFormatUtil; import freemarker.core.TemplateNumberFormat; import freemarker.core.TemplateNumberFormatFactory; import freemarker.core.TemplateValueFormatException; import freemarker.core.UnformattableValueException; import freemarker.template.TemplateModelException; import freemarker.template.TemplateNumberModel; import freemarker.template.utility.NumberUtil; import java.text.DecimalFormat; import java.util.Locale; /** * 將金額加上千分號,並註明新台幣 NT * <p> * 使用方式 ${total?string.@ntd},2380 會被轉換為 NT$2,380 */ public class NTDTemplateNumberFormatFactory extends TemplateNumberFormatFactory { public static final NTDTemplateNumberFormatFactory INSTANCE = new NTDTemplateNumberFormatFactory(); private static DecimalFormat ntdFormat = new DecimalFormat("NT$#,###"); private NTDTemplateNumberFormatFactory() { // Defined to decrease visibility } @Override public TemplateNumberFormat get(String s, Locale locale, Environment environment) throws TemplateValueFormatException { TemplateFormatUtil.checkHasNoParameters(s); return NTDTemplateStringFormat.INSTANCE; } private static class NTDTemplateStringFormat extends TemplateNumberFormat { private static final NTDTemplateStringFormat INSTANCE = new NTDTemplateStringFormat(); private NTDTemplateStringFormat() { // Defined to decrease visibility } /** * 2380 會被轉換為 NT$2,380 的邏輯寫在這裡 * * @param numberModel * @return * @throws TemplateValueFormatException * @throws TemplateModelException */ @Override public String formatToPlainText(TemplateNumberModel numberModel) throws TemplateValueFormatException, TemplateModelException { Number number = TemplateFormatUtil.getNonNullNumber(numberModel); try { return ntdFormat.format(NumberUtil.toIntExact(number)); } catch (RuntimeException e) { throw new UnformattableValueException(number + " - 金額轉換失敗", e); } } @Override public boolean isLocaleBound() { return false; } @Override public String getDescription() { return "數字轉新台幣"; } } }
Configuration cfg = new Configuration(Configuration.getVersion()); cfg.setClassForTemplateLoading(this.getClass(), "/"); // register the "ntd" format: Map<String, TemplateNumberFormatFactory> customNumberFormats = new HashMap<>(); customNumberFormats.put("ntd", NTDTemplateNumberFormatFactory.INSTANCE); cfg.setCustomNumberFormats(customNumberFormats);
<#-- 取得現在時間 --> <#assign aDateTime = .now> <#-- 只保留日期 --> <#assign aDate = aDateTime?date> <#-- create the macro variable: --> <#macro printDate mingguodate> 列印日期:${mingguodate} </#macro> <#macro footer records amount> ${"-"?right_pad(25, "-")} 總筆數:${records} 總金額:${amount} </#macro> <#-- call the macro: --> <@printDate mingguodate="${aDate?string.@mingguo}" /> <#assign total = 0> ${"水果名稱"?right_pad(10)}${"單價"?right_pad(10)}${"訂購數量"?right_pad(10)} ${"-"?right_pad(25, "-")} <#list rows as row> <#assign total += row.price * row.quantity> ${row.name?right_pad(10)}${row.price?string.@ntd?left_pad(10)}${row.quantity?left_pad(10)} </#list> <#-- call the macro: --> <@footer records="${rows?size?left_pad(10)}" amount="${total?string.@ntd?left_pad(10)}" />