개요

  • 편성표 방송 알림 Count를 알려주는 API를 개발한다.
    • 1) 이게 무슨 일을 하는 지, 현업에서 어떻게 활용할 지에 관한 설명
      • 은 듣고 이해했지만 내 개인 블로그에 기록으로 남기기는 귀찮다.
      • 내가 알아야 할 것!
        • 주어진 변수로 호출하면 주어진 정보들을 Return하면 된다.
    • 2) 흔한 API개발을 기록으로 남기는 이유
      • 업무적으로 내쪽 업무가 아니다.
        • 업무 협의(내가한거 아님) 과정에서 다 쳐내다보니 이 정도는 해주자 해서 넘어온 업무
        • 기존 Application과 성격도 다르고 언제 없어져도 이상하지 않기 때문에 별도의 Directory구조로 관리를 하는 것이 좋다고 판단
          • Spring Setting들을 다시 잡아줘야 했고 그 과정을 기록으로 남기고자 함

Log

 

  • 1. 영혼이 시키는 대로 디렉토리 및 파일 생성
+---java
|   \---iceberg
|       +---admin [기존소스]
|       +---common [기존소스]
|       \---external [New 디렉토리]
|           +---controller
|           |       ExternalAPIController.java [New source]
|           |       
|           +---domain
|           |       BrodAlarmInfo.java [New source]
|           |       
|           +---repository 
|           |   \---webdb
|           |           WebDbExternalAPISqlMapRepository.java [New source]
|           |           
|           \---service
|                   ExternalAPIService.java [New source]
|                   
+---resources
|   +---config
|   |   +---log
|   |   +---message
|   |   +---properties
|   |   +---spring
|   |   |       admin-datacontext.xml
|   |   |       admin-mapper-datacontext.xml
|   |   |       admin-servicecontext.xml
|   |   |       admin-webcontext.xml
|   |   \---sqlmap
|   |       |   sqlmap-config.xml
|   |       +---mysqldb
|   |       +---odsdb
|   |       +---schedule
|   |       +---smtcdb
|   |       \---webdb
|   |           +---deal
|   |           +---external [New 디렉토리]
|   |           |       WebDbExternalAPISqlMapRepository-sql.xml [New source]
|   |           +---monitor
|   |           +---navigation
\---webapp
  • 2. Controller/호출 URL작성
    • ExternalAPIController.java
      • 1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        @Controller
        @RequestMapping(value = "/□□□□")
        public class ExternalAPIController {
            
            private ExternalAPIService externalAPIService;
         
            @Autowired
            public void setExternalAPIService(ExternalAPIService externalAPIService){
                this.externalAPIService = externalAPIService;
            }
            
            @ResponseBody
            @RequestMapping(value = "/□□□□-□□□□-□□□□", method = RequestMethod.GET)
            public List<BrodAlarmInfo> getBrodAlarmCount(@RequestParam(value="broadType", required = trueString broadType) {
                BrodAlarmInfo paramMap = new BrodAlarmInfo(broadType);
                return externalAPIService.getBrodAlarmCount(paramMap);
            }
        }
        cs

 


    • URL
      • http://localhost:8080/□□□□/□□□□?broadType=DATA
      • http://localhost:8080/□□□□/□□□□?broadType=TV
    • webContext.xml : Exception pattern에 호출 URL 등록
  • Postman으로 일단 Call (될리가 없을걸 알지만)
    • Postman기능들 나중에 좀더 살펴보기
  • 2-1.  오류
1
2
3
4
5
6
org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'GET' not supported
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:196)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:284)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:231)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:56)
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:297)
cs
  •  
    • 오류내용
      • 해당 URL로 호출 되는 Contoller를 찾지 못함
      • 새로 만든 Controller가 기존의 ComponentScan하는 Directory 외부에 있어 @Controller tag를 읽어서 Bean으로 등록하지 못함
    • 해결 : 기존 webContext.xml - Componet Scan 부분에 새로만든 Directory 추가
1
2
3
4
    <context:component-scan base-package="iceberg.admin, iceberg.external" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
 
cs

 

  • 3. Domain(DTO) 및 서비스 생성
    • Domain 생성 : 정의서 보고 대충만들면 된다
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package iceberg.external.domain;
 
import java.io.Serializable;
 
public class BrodAlarmInfo implements Serializable{
    
    private static final long serialVersionUID = 1L;
 
    private String broadType;
    private String broadDate;
    private String closingDate;
    private String onair;
    private int prdCd;
    private String prdNm;
    private int alarmCnt;
    
    public BrodAlarmInfo(){
    }
    
    public BrodAlarmInfo(String broadType){
        this.broadType=broadType;
    }
    /* Getter & Setter */
}
 
cs
      • lombok도 마음대로 추가 못하는 내 처지ㅎㅎ
    • 서비스도 영혼이 시키는 대로 만들기
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Service
    public class ExternalAPIService {
        private final WebDbExternalAPISqlMapRepository webDbExternalAPISqlMapRepository;
     
        @Autowired
        ExternalAPIService(WebDbExternalAPISqlMapRepository webDbExternalAPISqlMapRepository){
            this.webDbExternalAPISqlMapRepository = webDbExternalAPISqlMapRepository;
        }
        
        public List<BrodAlarmInfo> getBrodAlarmCount(BrodAlarmInfo paramMap){
            return webDbExternalAPISqlMapRepository.getBrodAlarmCount(paramMap);
            
        }
    }
     
    cs
  •  
        • 3-1. 오류 (2)
    1
    2
    3
    servlet.DispatcherServlet.initServletBean(470- Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'externalAPIController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void iceberg.external.controller.ExternalAPIController.setExternalAPIService(iceberg.external.service.ExternalAPIService); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [iceberg.external.service.ExternalAPIService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:289)
    cs
      •  
        • 오류내용 Controller에서 호출하는 Service bean을 Bean factory에서 찾을 수 없음
          • 새로 만든 Service가 기존의 Component-Scan하는 Directory 외부에 있어 @Service tag를 읽어서 Bean으로 등록하지 못함
        • 해결 : 기존 webContext.xml - Componet Scan 부분에 새로만든 Directory 추가
          •  
            1
            2
            3
            4
            5
            6
            7
            <context:component-scan base-package="iceberg.admin, iceberg.external" use-default-filters="false">
                        <context:include-filter type="annotation"    expression="org.springframework.stereotype.Service" />
                        <context:include-filter type="annotation"    expression="org.springframework.stereotype.Repository" />
                        <context:include-filter type="annotation"    expression="iceberg.admin.common.annotation.Processor" />
                        <context:include-filter type="annotation"    expression="iceberg.admin.common.annotation.Factory" />
                        <context:include-filter type="annotation"    expression="iceberg.admin.common.annotation.AopProcessor" />
            </context:component-scan>
            cs
      • 3-2 Service ------[DTO]-----> Repository
        • Iceberg Framework에서 세팅하는 부분들이 있다. 
          • Iceberg에 SimpleSqlMapRepository를 구현해서 사용하는데 따라가보니 SimpleJPARepository도 있다. 여기서는 JPA를 사용하지 않지만 사용할 수 있게 프레임워크에서 제공하는 걸로 보인다. 나중에 써봐야겠다.
        • 오류들을 잘 읽어서 해결

 

3-2. 기타등등 Setting

  • WebDbExternalAPISqlMapRepository.java
1
2
3
4
5
public interface WebDbExternalAPISqlMapRepository extends SimpleSqlMapRepository<StringString> {
    List<BrodAlarmInfo> getBrodAlarmCount(BrodAlarmInfo param);
 
}
 
cs
  • WebDbExternalAPISqlMapRepository-sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="iceberg.external.repository.webdb.WebDbExternalAPISqlMapRepository">
    
<resultMap type="brodAlarmInfo" id="brodAlarmInfoMap">
    <result column="BROAD_TYPE" property="broadType"/>
    <result column="BROAD_DATE" property="broadDate"/>
    <result column="CLOSING_DATE" property="closingDate"/>
    <result column="ONAIR" property="onair"/>
    <result column="PRD_CD" property="prdCd"/>
    <result column="PRD_NM" property="prdNm"/>
    <result column="ALARM_CNT" property="alarmCnt"/>
</resultMap>
    
<select id="getBrodAlarmCount" resultMap="brodAlarmInfoMap" parameterType="brodAlarmInfo">
    SELECT 
    FROM
    WHERE
    
</mapper>
 
cs
  • sqlmap-config.xml
1
2
3
<typeAliases>
        <package name="iceberg.external.domain" />
</typeAliases>
cs

mapper-datacontext.xml

1
2
3
4
5
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="iceberg.external.repository.webdb" />
        <property name="markerInterface" value="iceberg.framework.core.repository.sqlmap.SimpleSqlMapRepository" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
cs

 

 

[마무리]

  • Domain - Service - Controller 까지 전부 다 만들어 본 적은 오랜만이었다. 회사일은 보통 누군가 만들어놓은 구조에 맞춰서 하다보면 원리도 모르고 그냥 되는 경우가 대부분이다. 이번 업무를 통해서 이 어플리케이션의 전체적인 동작 구조를 더 잘 알 수 있었다.
  • 포스팅 쓰다보니 귀찮고 내용도 뭔가 깔끔하지가 않아서 짜증난다. 오늘은 이 정도에서 마무리하자 하다보면 요령이 생기겠지뭐...
  •  

+ Recent posts