잡글

링크 : http://www.hanb.co.kr/ebook/look.html?isbn=9788968486128

5번째로 주문한 한빛의 Ebook이다. 작년부터 spring batch와 integration의 연결을 생각하고는 있었지만, 니즈가 없어서 관심대상에만 올려놓고 있었다. 이번 프로젝트에서는 필요가 있을듯한 기운이 감돌고, 빠른 학습을 위해 마침 출간된 이 책을 구입하였다.

(자바지기님의 좋은 글도 있다 : http://www.javajigi.net/pages/viewpage.action?pageId=267517955)

기존 내가 관리하던 레거시 플랫폼의 로직들에 적용하면 좋을만한 선언적 명세(?)들이 다양하지만... Acegi & Security에서 겪은 '선언의 획일성' 때문에 다시 코드를 풀어쓰지 않을까? 라는 느낌이 든다.  그리고 내가 정말 필요로 해서 써야하는가도 아직은 잘 모르겠다. 

100page의 책은 대략적으로 정의에 대해서 소개가 되어 있는편이라. 

http://blog.springsource.org/category/spring-integration/

http://www.springsource.org/spring-integration 를 더 봐야할것같다...


고민이.. 모니터에 스치운다. .. 


신고

SqlMapClientTemplate 의 내부

spring framework 2013.02.01 10:16 posted by dev.bistro


Source Link


public int delete(final String statementName, final Object parameterObject)

throws DataAccessException {


return execute(new SqlMapClientCallback<Integer>() {

public Integer doInSqlMapClient(SqlMapExecutor executor) throws SQLException {

return executor.delete(statementName, parameterObject);

}

});

}




1. 모든 처리를  public execute 메소드가 위임 받는다.

2. public execute 는SqlMapClientCallback<T> action 를 argument로 받는다.

3. delete, queryForObject 등의 위임을 하는 펑션들은 콜백 펑션을 선언해서 execute를 실행한다.

4. 실제적으로 executor 은 SqlMapClientTemplate에 DI된 sqpMapClient에서 가져와 쓰여진다.


이정도가.. 기본 로직인거고.

1. execute가 적절한 예외처리를 해줌으로서 Exception에 대한 부담이 줄어든다.

2. 적절한 공통코드를 알아서 처리해준다(close같은..)

SqlMapClientTemplate은 여러이유에서 SqlMapClient를 래핑한 Helper 클래스 이다.

템플릿 패턴의 모범적인 적용사례(?)

신고

DefaultServletHttpRequestHandler

spring framework 2013.02.01 09:22 posted by dev.bistro


Source Link

anyframe document Link


* @author Jeremy Grelle 

* @author Juergen Hoeller 

* @since 3.0.4


public void handleRequest(HttpServletRequest request, HttpServletResponse response)

throws ServletException, IOException {


RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName);

if (rd == null) {

throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" +

this.defaultServletName +"'");

}

rd.forward(request, response);

}


<mvc:default-servlet-handler/> 의 실제 구현체, DispatcherServlet이 제어하지 못하는 리소스를 만나면, 서버의 디폴트 서블릿으로 요청을 넘긴다. 



신고

Spring Batch Admin

spring framework/spring-batch 2013.01.11 17:34 posted by dev.bistro


단순히, Batch모듈을 쓰고 있다가. Integration과 함께 무엇을 할 것인가에 대한 고민중이다.

앞서, 이전 프로젝트에서는 Batch가 어떻게 얼마나 잘 돌았는지 보려고 Batch Admin이라는 유틸성 프로젝트를 연결해보았다. 



내가 쓰던 JobRepository를 연결하고, 실행하면 내 잡들 목록과, BatchAdmin의 기본 잡 2개가 리스트에 나온다. 




각 Job의 실행값들과 결과를 알수있고, Step단계로도 확인할 수 있다.

Step 까지 클릭해서 들어가면 Exit Message도 볼수 있어 배치 실패 이슈를 쉽게 파악할 수 있다.


문제는....

1. 기존의 신규 배치가 아직, 잘 돌아가는 구 배치들이 JobRepository에 맞춰서 (기존 logfile이 아닌, remote log를 쌓아줘야하고...) 또는 SpringBatch로 만들거나...

2. Remote Launch가 프로젝트 파티셔닝 상황에서 잘 되는지도 봐야하고...

3. UI도 맘에 안들고-.-;;; 


신고

'spring framework > spring-batch' 카테고리의 다른 글

JAXP DOM4J, JDOM2의 성능 비교  (0) 2013.11.13
Spring Batch Admin  (0) 2013.01.11
JobLauncher, SimpleJobLauncher  (0) 2012.08.28
JobParametersIncrementer의 사용.  (0) 2012.08.25

SpringOne2GX 2012 컨퍼런스 후기 나눔 세미나 


#1. Spring

Spring 3.1  (Dec.2011) 

 -  beans profile 기능

 -- <beans profile="test"> 으로 설정

 -- 자바코드, System환경변수 -Dspring.profile.action="test", web.xml 에서 설정가능 총 3가지

 

 - Java-based Configuration

 -- Type safe (컴파일시 오류 확인)

 -- Bean 생성에서 로직을 추가할 수 있음 (동적 구성)

 

 - servlet3.0

 -- 스펙중 하나 : 필터/서블릿/리스너 등을 자동 스캔할 수 있다. (기존에는 web.xml에 종속적)


 - cache by annotation

 -- 파라미터 기반으로 캐싱기능


Spring 3.2 (Dec.2012)

- Groovy 기반 Gradle-based빌드, SCM: github

- Java7 기반 빌드 (하지만 하위 호환성 유지위해 Java5,6 빌드도 있다)

- proxy등에 밀접 CGLIB3.0, ASM 4.0을 인라인으로 포함해버림 (기존에는 외부jar였다)

- Async MVC 


Spring 3.3 (Q4 ,2013)

- Java 8 / Java EE 7 예정

-  message기반에 초점 (jms / websocket)

- Date and Time API (JSR-310)



#2 Spring integration & batch

Spring integration 

 - 기존 integration style : B2B, EAI (File transfer, share DB, Remoting, Messaging)

 - Spring.integartion은 기존에 알려진 엔터프라이즈 인테그레이션 패턴을 지원하기 위한 방법모델

 - Pipe(Channel), Filter(Endpoint) 의 핵심 개념

   Chaanel 구현체 : QueueChannel...


Spring batch

 - Batch의 특징

 -- Long run, Non-interactive, Process large data

Spring batch-admin 

 - Sub project of Spring Batch

 - WebUI제공, RESTFul방식으로 배치 제어가능

 - 외부 시스템과의 연계는 Integration + Batch로 많이 구현된다. (cron이 아니라 파일이 들어온다던지 어느 특정요건을 만족할경우...)

 Spring Data

  - 새로운 Data Access에 대한 지원 (서브 프로젝트 11개 ! )

  -- RDB : JPA, JDBC extensions //BIG DATA : HADOOP //HTTP : REST

  -- KV : Redis //Document : MongoDB //Graph : Neo4j //Column : HBase

  - Spring Data Repository가 일관된 Layer를 제공한다. 

  -- domain 과 data mapping 사이의 중계역할 

  -- interface CrudRepository 를 보면 된다.  (실제 DB를 접근하는 구현체에 신경쓰지 마라)

  - Domain mapping

  - 이 부분은 사용될 DB에 따라 조금씩 다르다.




Batch & Integration

* http://www.slideshare.net/hillert/introduction-to-spring-integration-and-spring-batch

* http://java.dzone.com/articles/enterprise-integration-and


Gradle

* http://blog.pizzicato.kr/12


신고

JobLauncher, SimpleJobLauncher

spring framework/spring-batch 2012.08.28 15:43 posted by dev.bistro

휴가중(진짜 심심해서 쓰는 ) 포스팅. 작성중


JobLauncher 의 유일한 구현체 SimpleJobLauncher이다.

1. 유일한 public method 'run'을 보면 Job , JobParameters 를 아귀먼트로 받는것을 확인할 수 이고,  return 은  JobExecution이다.

2. JobExecution은 Entity를 상속받는 상태를 나타내는 클래스라 생각해도 된다.



/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.batch.core.launch.support;

/**
 * Simple implementation of the {@link JobLauncher} interface. The Spring Core
 * {@link TaskExecutor} interface is used to launch a {@link Job}. This means
 * that the type of executor set is very important. If a
 * {@link SyncTaskExecutor} is used, then the job will be processed
 * within the same thread that called the launcher. Care should
 * be taken to ensure any users of this class understand fully whether or not
 * the implementation of TaskExecutor used will start tasks synchronously or
 * asynchronously. The default setting uses a synchronous task executor.
 * 
 * There is only one required dependency of this Launcher, a
 * {@link JobRepository}. The JobRepository is used to obtain a valid
 * JobExecution. The Repository must be used because the provided {@link Job}
 * could be a restart of an existing {@link JobInstance}, and only the
 * Repository can reliably recreate it.
 * 
 * @author Lucas Ward
 * @Author Dave Syer
 * 
 * @since 1.0
 * 
 * @see JobRepository
 * @see TaskExecutor
 */

public class SimpleJobLauncher implements JobLauncher, InitializingBean {
	protected static final Log logger = LogFactory.getLog(SimpleJobLauncher.class);
	private JobRepository jobRepository;
	private TaskExecutor taskExecutor;

	/**
	 * Run the provided job with the given {@link JobParameters}. The
	 * {@link JobParameters} will be used to determine if this is an execution
	 * of an existing job instance, or if a new one should be created.
	 * 
	 * @param job the job to be run.
	 * @param jobParameters the {@link JobParameters} for this particular
	 * execution.
	 * @return JobExecutionAlreadyRunningException if the JobInstance already
	 * exists and has an execution already running.
	 * @throws JobRestartException if the execution would be a re-start, but a
	 * re-start is either not allowed or not needed.
	 * @throws JobInstanceAlreadyCompleteException if this instance has already
	 * completed successfully
	 * @throws JobParametersInvalidException
	 */

	public JobExecution run(final Job job, final JobParameters jobParameters)
			throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException,
			JobParametersInvalidException {

		Assert.notNull(job, "The Job must not be null.");
		Assert.notNull(jobParameters, "The JobParameters must not be null.");

		final JobExecution jobExecution;
		JobExecution lastExecution = jobRepository.getLastJobExecution(job.getName(), jobParameters);
		if (lastExecution != null) {
			if (!job.isRestartable()) {
				throw new JobRestartException("JobInstance already exists and is not restartable");
			}
		}

		// Check the validity of the parameters before doing creating anything
		// in the repository...
		job.getJobParametersValidator().validate(jobParameters);

		/*
		 * There is a very small probability that a non-restartable job can be
		 * restarted, but only if another process or thread manages to launch
		 * and fail a job execution for this instance between the last
		 * assertion and the next method returning successfully.
		 */

		jobExecution = jobRepository.createJobExecution(job.getName(), jobParameters);

		try {
			taskExecutor.execute(new Runnable() {

				public void run() {
					try {
						logger.info("Job: [" + job + "] launched with the following parameters: [" + jobParameters
								+ "]");
						job.execute(jobExecution);
						logger.info("Job: [" + job + "] completed with the following parameters: [" + jobParameters
								+ "] and the following status: [" + jobExecution.getStatus() + "]");
					}
					catch (Throwable t) {
						logger.info("Job: [" + job
								+ "] failed unexpectedly and fatally with the following parameters: [" + jobParameters
								+ "]", t);
						rethrow(t);
					}
				}

				private void rethrow(Throwable t) {
					if (t instanceof RuntimeException) {
						throw (RuntimeException) t;
					}
					else if (t instanceof Error) {
						throw (Error) t;
					}
					throw new IllegalStateException(t);
				}
			});
		}
		catch (TaskRejectedException e) {
			jobExecution.upgradeStatus(BatchStatus.FAILED);
			if (jobExecution.getExitStatus().equals(ExitStatus.UNKNOWN)) {
				jobExecution.setExitStatus(ExitStatus.FAILED.addExitDescription(e));
			}
			jobRepository.update(jobExecution);
		}

		return jobExecution;
	}

	public void setJobRepository(JobRepository jobRepository) {
		this.jobRepository = jobRepository;
	}

	public void setTaskExecutor(TaskExecutor taskExecutor) {
		this.taskExecutor = taskExecutor;
	}

	public void afterPropertiesSet() throws Exception {
		Assert.state(jobRepository != null, "A JobRepository has not been set.");
		if (taskExecutor == null) {
			logger.info("No TaskExecutor has been set, defaulting to synchronous executor.");
			taskExecutor = new SyncTaskExecutor();
		}
	}

}

---
public class JobExecution extends Entity {
	private JobInstance jobInstance;
	private volatile Collection stepExecutions = new CopyOnWriteArraySet();
	private volatile BatchStatus status = BatchStatus.STARTING;
	private volatile Date startTime = null;
	private volatile Date createTime = new Date(System.currentTimeMillis());
	private volatile Date endTime = null;
	private volatile Date lastUpdated = null;
	private volatile ExitStatus exitStatus = ExitStatus.UNKNOWN;
	private volatile ExecutionContext executionContext = new ExecutionContext();
	private transient volatile List failureExceptions = new CopyOnWriteArrayList();

       하략 ... 대부분 생성자/Get/Set



참고#1: http://chanwook.tistory.com/797

요약 : 4년전 교육 받았을때도 느꼈지만... 박찬욱님 짱 :)

신고

'spring framework > spring-batch' 카테고리의 다른 글

JAXP DOM4J, JDOM2의 성능 비교  (0) 2013.11.13
Spring Batch Admin  (0) 2013.01.11
JobLauncher, SimpleJobLauncher  (0) 2012.08.28
JobParametersIncrementer의 사용.  (0) 2012.08.25


Job Parameter를 자동으로 Increment 하기 위해서 사용.

(Job의 구현체를 구분하는 방법은 Job + Job Parameter이기 때문에, Parameter없이는 같은 job을 계속 실행하면 안된다)





@Component
public class SimpleJobParametersIncrementer implements JobParametersIncrementer {

	static final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd-hhmmss");
	public JobParameters getNext(JobParameters parameters) {
		String id = format.format(new Date());
		return new JobParametersBuilder().addString("run.id", id).toJobParameters();
	}

}
	
        
	    
	

	
		


요약
1. JobParametersIncrementer 구현
2. JobExplorerFactoryBean bean 설정
3. job에 increment로 1번 설정
4. 실행은 xmlfile jobanme [-next] 를 추가

참고

http://numberformat.wordpress.com/2010/02/07/multiple-batch-runs-with-spring-batch/


참고2 [BATCH_JOB_PARAMS] 테이블

JOB_INSTANCE_ID TYPE_CD KEY_NAME STRING_VAL DATE_VAL LONG_VAL DOUBLE_VAL

3 STRING run.id 20120825-124631 1970-01-01 09:00:00 0 0

4 STRING run.id 20120825-125909 1970-01-01 09:00:00 0 0


참고3. 기본적으로 제공하는 crementer는

org.springframework.batch.core.launch.support.RunIdIncrementer 가 있고 key를 프로퍼티로 받는다. 

https://fisheye.springsource.org/browse/spring-batch/spring-batch-core/src/main/java/org/springframework/batch/core/launch/support/RunIdIncrementer.java?r=488ba7a37b70c62a2ac40d6c945ea940408add80


신고

'spring framework > spring-batch' 카테고리의 다른 글

JAXP DOM4J, JDOM2의 성능 비교  (0) 2013.11.13
Spring Batch Admin  (0) 2013.01.11
JobLauncher, SimpleJobLauncher  (0) 2012.08.28
JobParametersIncrementer의 사용.  (0) 2012.08.25


spring-data-mongodb 가 1.0 RC1 발표 하고 바로 한달도 안되 바로 GA 까지 발표하였다.
기존에 M2 버전부터 시작해서 버전이 올라 갈때마다, method signature가 변경되는등, 사용하는데 어려움이 많았는데 이제 다시 한번 봐도 될 시점인듯 하다.

changelog를 살펴보니 M4버전에서 MongoTemplate에 mapreduce를  지원하는게 보이니 (DATAMONGO-7) 기존의 Command에서 처리하였던 Map-Reduce부분, upsert등 몇몇 부분을 수정해야겠다.


News :  http://www.springsource.org/node/3346 



 
신고

'spring framework > spring-data' 카테고리의 다른 글

Spring Data MongoDB 1.0.0.RC1 Released  (0) 2011.12.29


티스토리 툴바