RestOperations

springBoot gradle 2017. 2. 6. 21:59

spring 컨트롤러나 서비스 등의 안에서, 웹 서비스를 접속할 필요가 있을경우 RestTemplate(혹은 RestOperation)을 이용하면 편리하다.

REF


get/post

    For

Object/Entity 의 형태로 함수명이 존재한다.


즉 결과를 Object형태로 받을 수도 있고, Entity형태로 받을 수도 있다. 


파라미터로

-Object, Map, ClassType 등을 다양하게 이용할 수 있다.



patch/update/delete/option 함수들도 존재한다. 

Posted by yongary
,

간단한 테이블 디자인은 bootstrap css 에서 가져다 쓰는게 최선인것 같다.


기본적으로 column은 12column을 기본으로 하므로,  12안에서 나누어쓰면 된다.

관련해서 bootstrap은 크기별 이름명명 규칙이 있다.   REF



테이블 디자인 class도 사전에 정의되어 있다.  REF

Posted by yongary
,

@Cacheable

springBoot gradle 2017. 1. 21. 22:42

REF   REF한글


REF_NEW(good config)


spring에서

@Cacheable


@Cacheevict


@Cacheput 


을 이용해서 각종 조건을 지정하면서... 함수 리턴결과 등을 cache할 수 있다.


단, Cacheable등은 proxy형태의 AOP이므로, 별도 class를 만들어서 추가해야 한다.


@CacheConfig(cacheNames = CacheManagerConfig.DEFAULT_CACHE_NAME) public class ForCacheService {

@Cacheable(key = "'myCache'")
public Optional<Something> findSomething(){
return db.findSomething();
}

@CacheEvict(key = "'myCache'")
public void clearCache() {
log.info("clear cache: key=myCache");
}

}

 ==> 음 Optional은 serialize가 안되서 Cache가 안되는 문제 발견.

일반 class 일 경우에도 implements Serializable을 해야 한다.




null Value가 cache가 안되도록 하려면  다음과 같이 #unless를 이용하면 된다.  REF

  (unless는 함수가 실행된 이후에 평가됨.  즉, cache가 있을때는 상관없이 pass.)


@Cacheable( key="'myCache'", unless="#result == null")
public Person findPerson(int pk) {
   return getSession.getPerson(pk);
}


null Value도 cache가 되도록 하고 싶으면? ==>안됨.


Posted by yongary
,

REF-spring  REF-etc     Validataion-Group



spring 에는 annotation으로 form 필드를 자동으로 체크할 수가 있다.


일반적으로는 

xxForm.java 파일을 하나 만들고 그 안에 Form과 일치하도록 모든 Field를 정의한 다음에...


각 필드별로 여러가지 constraint를 정의할 수 있다. 


@Pattern :  Regex패턴 체크.

@NotNull  @Null 

@Size(min=2, max=30) 

@Past (지난 날짜) @Future

@Max @Min @DecimalMax @DecimalMin 2Digits

@AssertFalse @AssertTrue


<기본사용>


예제)
public class MyForm {

@NotNull(message = "{error.not_input}")
@Length(max = 3, message = "{error.max_length}")
private String age;

@NotNull(message = "{error.not_input}")
@Length(max = 255, message = "{error.max_length}")
private String name;

@Pattern(regexp = MyConstant.MAIL_ADDRESS, message = "{error.mail_address_format_error}")

private String email;


}

 

컨트롤러에서 아래와 같은 형태로 값을 받는다.

public String checkPersonInfo(@Valid PersonForm personForm, BindingResult bindingResult)




==========1=====================

간단히 Override로 Custom Validator를 만들 수 있다.

@Data
@NoArgsConstructor
@CmsMemberMailValidator(newMailAddressField = "newMailAddress", mailConfirmField = "mailConfirm")
public class CmsMemberMailModifyForm {

private Long id;

private String displayName;

private String status;

private String organizationName;

private String mailAddress;

@NotNull(message = "{error.mail_address_null_error}")
@Pattern(regexp = WebConstantShared.MAIL_ADDRESS, message = "{error.mail_address_format_error}")
private String newMailAddress;

@NotNull(message = "{error.mail_address_null_error}")
private String mailConfirm;

public static CmsMemberMailModifyForm of(CmsMemberDetail cmsMemberDetail) {
CmsMemberMailModifyForm form = new CmsMemberMailModifyForm();
BeanUtils.copyProperties(cmsMemberDetail, form);
return form;
}
}

 


@Target({ TYPE }) @Documented
@Retention(RUNTIME)
@Constraint(validatedBy = Validator.class)
public @interface CmsMemberMailValidator {
String message() default "{error.mail_address_format_error}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String newMailAddressField();
String mailConfirmField();
class Validator implements ConstraintValidator<CmsMemberMailValidator, Object> {
private String message;
private String newMailAddressField;
private String mailConfirmField;
@Override
public void initialize(CmsMemberMailValidator constraintAnnotation) {
message = constraintAnnotation.message();
newMailAddressField = constraintAnnotation.newMailAddressField();
mailConfirmField = constraintAnnotation.mailConfirmField();
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
BeanWrapper beanWrapper = new BeanWrapperImpl(value);
String newMailAddressValue = (String) beanWrapper.getPropertyValue(newMailAddressField);
String mailConfirmValue = (String) beanWrapper.getPropertyValue(mailConfirmField);
//check only different case (null & blank Error_Message is processed on @NotNull annotation)
if (newMailAddressValue != null && StringUtils.isNotBlank(newMailAddressValue)
&& mailConfirmValue != null && StringUtils.isNotBlank(mailConfirmValue) && !mailConfirmValue
.equals(newMailAddressValue)) {
context.disableDefaultConstraintViolation();
context.buildConstraintViolationWithTemplate(message)
.addPropertyNode(mailConfirmField)
.addConstraintViolation();
return false;
}
return true;
}
}
}


==========2===================

위보단 약간 복잡하지만 좀 더 많은 기능이 있는 @InitBinder를 이용해

Custom Validator를 만들 수 있다.


Custom Validator: spring-REF   Ref-InitBinder

Custom Validation Class를 만들 수도 있다.

.  



< Valid vs Validated >  REF1simple, REF2,


Validated는 spring 소속이고, Valid는 java소속인데

Validated가 Validataion-Group을 지정할 수 있다.



 에러메시지도 출력가능하다.   REF




Posted by yongary
,

javascript로 이메일 verification하는 스크립트가 왜케 복잡한 것만 있는지..


인터넷에 마음에 드는 게 없어서 새로 만들어 보았다.



//check if mail address is xx@xx.xx (xx: contains "." & "_" & "-" & "alphanumeric" )
function validateEmail(email) {
var re = new RegExp("^[-a-zA-Z0-9._]+@[-a-zA-Z0-9._]+\\.[-a-zA-Z0-9._]+$");
return re.test(email);


코멘트 처럼  xx@xx.xx  폼을 체크하는데  xx 는  - . _ 알파뉴메릭  으로 이루어진다. 



조금 더 발전하면.. (이건 다른사람 꺼)

"[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})";


Posted by yongary
,

Selenium 을 이용하면 여러 브라우저를 직접구동시켜 다양한 테스트를 수행하므로

고급 웹서비스에서는 이 방식을 사용하는 것이 좋다.


하지만 간단한 웹페이지라면 이런방식이 부담이 될 수 있는데,

간단한게  spring의  HtmlUnit을 이용하면 되지만(REF) 약간 부족한 부분을

Selenium의 WebDriver만 이용하는 방법이 있다.    이경우 Selenium서버는 필요없다. REF


<비교설명> REF  챕터2.

Posted by yongary
,

MockMvc

Spring 2017. 1. 6. 15:26

영문 spring test 환경 (MockMVC+Junit) 기본설명  : REF


영문Test Guide URL



Spring에서 지원하는 MockMvc로도 거의 모든 테스트가 가능하다.

(가끔 Mockito가 필요하면 둘을 섞어서 쓰면 되는 정도로 보인다)



이전엔 Mockito가 많이 필요했지만, 필요성이 조금 줄어든 것 같다.



아래는 MockMvc로 컨트롤러를 테스트 하는 예제이다. 

  - Controller Test annotation (spring-boot 1.4 부터 지원:)  REF




<MockMVC 기본>  REF

1. Request

-perform

-accept

-with

-param

-cookie

-sessionAttr


2. Response

-andExpect

-andDo

-andReturn



<andExpect> 에서 여러가지 확인이 가능한데.. 주로 많이 쓰는 것들은

.andExpect(status().isOk())
.andExpect(content().json(expected));
.andExpect(status().is3xxRedirection());

.andExpect(view().name("list"))
.andExpect(MockMvcResultMatchers.model().size(1));

등등이다.



ModelAndView: 데이타가 복잡할 경우에도 테스트가 가능한데....  

        View name = redirect:view

             View = null

        Attribute = MyTicketReserveResult

            value = MyTicketReserved(code=0009, msg=nulll)

           errors = []


와 같은 json을 확인하려면.. (아직 확인 중)


.andExpect(jsonPath("$[1].rtncd").value("0009"))


Posted by yongary
,


Spring 에서  web Test시에 user를 mock하는 방법으로 2가지를 현재 보고 있는데,

차이점이나 장단점에 대해서는 좀 더 공부를 할 예정이다.



1. import org.springframework

        .security.authentication.UsernamePasswordAuthenticationTokenREF


  

UserDetails user = this.userDetailsService.loadUserByUsername(username);

        UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(
                        user, 
                        user.getPassword(), 
                        user.getAuthorities());



2. import static org.springframework

         .security.test.web.servlet.request

         .SecurityMockMvcRequestPostProcessors.user;


  RequestBuilder request = get("/my_web_url")

  .with(user (myUser));



AuthenticationManager 참고: REF

Posted by yongary
,

Mockito 사용법

Spring 2016. 12. 28. 18:09

javadoc   한글개요   goodTutorial



Mockito에서   @Mock @InjectMocks @Spy 의 차이점:

(작성 중: 현재 정확하지 않음)


@InjectMocks를 우선 사용해서 서비스/Controller등을 만들고

컴포넌트를 @Mock를 이용해서 삽입한다.  REF


둘을 하나의 object에 동시에 사용하고 싶을 경우, 동시에 사용할 수 없기 때문에

@InjectMocks와 @Spy를 동시에 사용할 수 있는데

이경우  when()함수를 사용하면 실제 함수를 호출하기 때문에  doReturn함수를 사용한다.  Ref



<검사함수들>

when  :  mock객체는 기본값을 return하기 때문에 Stubbing을 통해 원하는 값을 리턴한다.      REF

 - when(mockedGenerator.getNextId()).thenAnswer(new Answer<Integer>(


assertTrue

  assertNotNull


doReturn  Ref   -override도 가능.

  doThrow  -  void type을 stub할때, when이 java문법에 맞지않아서  
                    doThrow(new Exception()).when(mock).method() 이렇게 사용.

  doNothing

           ex) doNothing().when(authenticationManager).authenticate(Matchers.any(Authentication.class)); 

  doAnswer 

           ex) 

doAnswer(new Answer<Authentication>(){

@Override
public Authentication answer(final InvocationOnMock invocation) throws Throwable {


//case token

ObjectPostProcessor<Object> objPostProc = (
new ObjectPostProcessor<Object> () {
public Object postProcess(Object bean) throws BeansException {
System.out.println("BeforeInitialization : " );
return bean; // you can return any other object as well
}
});

final PreAuthenticatedAuthenticationToken token = (PreAuthenticatedAuthenticationToken)(invocation.getArguments())[0];
Authentication authentication = (new AuthenticationManager(){
@Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
return (new AuthenticationManagerBuilder(objPostProc)).getOrBuild().authenticate(authentication);
}
}).authenticate(token);
return authentication;
}

}).when(authenticationManager).authenticate(Matchers.any(Authentication.class));



Verify 사용법 : test된 코드들의 횟수체크.. . REF

  - verify ( object,  atMost/never/times/atLeast/timeout ).함수명(  any(param) OR eq(param) ) 등.


InOrder  :  object간 순서 체크. 

verifyNoMoreInteractions : mock의 행동 다 검증했는지 확인.


Posted by yongary
,

thymeleaf 기본.

FRONT-END 2016. 12. 19. 22:18

REF-Tutorial

REF기본:

REF-dateForamtter등 발전된기능  {{}}:dateFormatter

(단, 이경우는 WebMvcConfig.java나 xml등에 addFormatter override나, formatter지정이 필요. Ref안에 xml은 있음)


spring의 thymeleaf를 통해  java의 EL을 html에 사용하는 듯한 느낌으로 사용할 수 있다.


@{ }로 사용하는 Variable expression은 java의 EL과 동일하고,

그 외에도 다음과 같은 것들이 있다.


  • ${...} : Variable expressions     - iterator처럼 반복도 지원된다.
  • *{...} : Selection expressions.   - th:object = ${book}과 같이 $로 선택된 object내에서 동작한다.  
  • #{...} : Message (i18n) expressions. - 다국적 메시지 지원.
  • @{...} : Link (URL) expressions.  -변수 파라미터도 가능하고, 상대경로 URL도 가능
            ex)  th:href="@{'/app/user/'+${user.id}+'/bustickets'}
  • ~{...} : Fragment expressions.  - 주로 div안으로 삽입 가능.


thymeleaf 로 form을 submit할 때는 다음과 같다.   REF

<form action="#" th:action="@{/greeting}" th:object="${greeting}" method="post">
    	<p>Id: <input type="text" th:field="*{id}" /></p>
        <p>Message: <input type="text" th:field="*{content}" /></p>
        <p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
    </form>

@{/greeting} : 처리할 URL

${greeing} : model형태로 넘길 object

th:text 보다는 th:field를 써야 object매핑이 되겠군요.



<table if  사용법>   REF

<td th:if="${member.status} == '1'" th:text="Active"></td>
<td th:unless="${member.status} == '1'" th:text="Inactive"></td>

<a th:if="${history.myProject.payType eq 'credit_card'}"

==> { }안에서 string비교시 eq도 사용가능.



<switch >

<td class="col-sm-2" th:switch="${ticket.status}">
<span th:case = 'unused'> "Unused"</span>
<span th:case = 'used'> "Used"</span>
<span th:case = 'unknown'> "Unknown"</span>
</td>


<enum사용시>

<td class="col-sm-1" th:if="${ticket.type == T(my.constant.TicketType).PAID}" th:text="Paid"></td>

${ticket.isExpired()}와 같이 public 함수도 사용이 가능하다. 


==고급===

[[ ]]  in-line 프로그래밍.  REF

${{ }} 자동변환.  REF


==th 함수==

${#strings.isEmpty(...))}

${#lists.size(...)}


th:block  - 매우 유용. 전체 block을 if로 묶어서 나타내거나 숨길 수 있음.

  <th:block th:if="${@environmentHelper.isBeta()}">
   각종 javascript등.. 코드

</th:block>


Posted by yongary
,