選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
matthew.ng ce27af8df4 add simple code for MQTT connection 2年前
gradle/wrapper first commit 2年前
src add simple code for MQTT connection 2年前
.gitignore first commit 2年前
README.md first commit 2年前
build.gradle add simple code for MQTT connection 2年前
example.launch.json Saving wok's sensor data 2年前
gradlew first commit 2年前
gradlew.bat first commit 2年前
hs_err_pid10376.log Saving wok's sensor data 2年前
settings.gradle Saving wok's sensor data 2年前

README.md

frontend:

  • Routes.js (path: ‘xxxWin’ for Window component)
  • load js resources:
    // option 1
    items: [
      Ext.create('App.test.TestPanel',{
        title: 'Title 1'
      }),
      {
        xtype: 'panel',
        title: 'Title 2'
      }
    ]
    
    // option 2
    requires: ['App.xxxx.XxxxPanel'],
    items: [{
      xtype: 'test.testPanel',
      title: 'Title 1'
    }]
    
  • get component e.g.
    me.down('test\\.testPanel') //alias: 'widget.test.testPanel'
    
  • i18n: static/public/i18n/{locale}.json
    // component level
    bind: {
      text: '{i18n.xx.xx}'
    }
    // program level
    App.getI18n('xx.xx') // or App.getI18n().xx.xx
    
  • security
    • App.security.getUser()
    • App.security.isGranted(string | string[])
    • App.security.isGrantedAll(string[])

backend (draft):

  • vs code dev: example.launch.json
  • db migration: resources/db/changelog/changes/** (support subfolder)
    • suggested that one changeset with one DDL
    • filename: {yyyyMMdd}_{number}_{name}/{number}_{name}.sql
    • filename 2(optional): {yyyyMMdd}_{number}_{name}/{number}_{name}/{number}_{name}.sql
    --liquibase formatted sql
    
    --changeset {name}:{id}
    --comment: remarks (optional)
    CREATE TABLE `tableName` (
      `id` INT PRIMARY KEY AUTO_INCREMENT,
      `created` DATETIME NOT NULL DEFAULT NOW(),
      `createdBy` VARCHAR(30),
      `version` INT NOT NULL DEFAULT 0,
      `modified` DATETIME NOT NULL DEFAULT NOW(),
      `modifiedBy` VARCHAR(30),
      `deleted` BOOLEAN NOT NULL DEFAULT FALSE,
    
      `column1` INT NOT NULL,
      `column2` VARCHAR(255)
    );
    
  • controller
    • AbstractController
    • api: /public/** /protected/**
    • RequestBody Class (@NotNull, @NotBlank, @Min, @Max, @Pattern, etc...)
    @NotNull
    @Pattern(regexp = "^Y$|^N$")
    private String YesNo;
    
    • authentication check: @PreAuthorize
    • common response class DataRes, IdRes, RecrodsRes, SuccessRes
    • RESTfull api (http method, http status)
      • http status:
        • 404: record not found
        • 409: record_line not found or record_line not under the record (relation check)
        • 422: something wrong, (e.g. qty not enough)
      • suggest /save api (also allowed for POST: new, PUT: update)
        1. POST /xxxx/save
        2. body:
        {
          "id": 1, //update
          "xx": "xx",
          "updateLines": [
            {
              "id": null, // new
              "xx": "xx"
            },
            {
              // need a relation check
              "id": 1, //update
              "xx": "xx"
            }
          ],
          // need a relation check
          "deleteLineIds": [1, 2]
        }
        
    //example
    @RestController
    @RequestMapping("/xxxx")
    public class ExampleController extends AbstractController {
    
      @PostMapping('/xxx') // @GetMapping @DeleteMapping @PutMapping @PatchMapping
      //@ResponseStatus(HttpStatus.CREATED)
      //@PreAuthorize("hasAuthority('XXX_MAINT')")
      public Xxxx api (@RequestBody @Valid ReqClass req) {
      }
    
      @GetMapping('/{id}')
      public Xxxx getXxx (@PathVariable int id) {
      }
    }
    
  • service
    • AbstractService, AbstractIdEntityService, AbstractBaseEntityService
    • @Transactional(rollbackFor = Exception.class) for write, read only not need transaction
  • dao
    public Optional<User> findByUsernameAndDeletedFalse(String username);
    // same
    @Query("FROM #{#entityName} u WHERE u.deleted = FALSE AND u.username = :username")
    public Optional<User> findByUsername(@Param("username") String username);
    
  • entity
    • IdEntity, BaseEntity
    • validation: @NotNull, @NotBlank, @Min, @Max, @Pattern, etc...
  • jdbcDao
  • reduce @Autowired
    • use constructor
    • try separate class (e.g. FileListController, FileDownloadController)
  • return Optional instead of null
    • return Optional<T> : may null
    • return T : must not null
  • i18n: i18n/messages_{locale(underscore)}.properties
    • messageSource.getMessage("name", null, LocaleUtils.getLocale());
  • reporting:
    • excel:
      • files:
        • excel/{filename}.xlsx
        • excel/{filename}_zh-TW.xlsx
        • excel/{filename}_zh-CN.xlsx
      • load Workbook: ExcelUtils.loadTemplate("excel/{filename}");
      • send out Workbook: ExcelUtils.send(response, workbook, "filename"); // will output filename.xlsx
    • jasper
      • files:
        • reports/{filename}.jrxml
        • reports/{filename}_zh-TW.jrxml
        • reports/{filename}_zh-CN.jrxml
      • compile: JasperUtils.compile("reports/{filename}", params, new JRBeanCollectionDataSource(xxx), Map.of("subReport1","reports/{filename}"));
      • send out: JasperUtils.responsePdf(response, jRerpot, "filename"); // will output filename.pdf
  • mobile:
    • login: POST /mobile/login
    • logout: POST /mobile/logout
    • call api: http headers with
      1. X-ATT-DeviceId
      2. X-ATT-Access-Token