001// Copyright(c) 2015 POSCO ICT 002// Change history 003// 2015-07-10 / 1.1.0 / 004package com.poscoict.app.job; 005 006import java.lang.management.ManagementFactory; 007import java.lang.reflect.InvocationTargetException; 008import java.lang.reflect.Method; 009import java.sql.Connection; 010import java.sql.PreparedStatement; 011import java.sql.SQLException; 012import java.util.Date; 013import java.util.List; 014import java.util.Map; 015 016import javax.sql.DataSource; 017 018import org.apache.commons.dbcp2.BasicDataSource; 019import org.slf4j.Logger; 020import org.slf4j.LoggerFactory; 021import org.springframework.context.ApplicationContext; 022import org.springframework.context.support.ClassPathXmlApplicationContext; 023import org.springframework.jdbc.datasource.DataSourceUtils; 024import org.springframework.jdbc.support.JdbcUtils; 025 026import com.poscoict.glueframework.biz.control.GlueBizControlConstants; 027import com.poscoict.glueframework.biz.control.GlueBizProvider; 028import com.poscoict.glueframework.context.GlueContext; 029import com.poscoict.glueframework.context.GlueDefaultContext; 030 031/** 032 * Main 클래스. 033 * 034 * <pre> 035 * java [-option] com.poscoict.app.job.GlueSimpleJob [args..] 036 * 형태로 GlueSimpleJob 클래스를 실행한다. 037 * 038 * [args..] 부분의 첫번째는 history id, 두번째는 실행유형, 세번째부터는 사용자 data로 구성한다. 039 * <xmp> 040 * java [-option] com.poscoict.app.job.GlueSimpleJob -1 ServiceName=job001-service@S userKey=userData@S 041 * java [-option] com.poscoict.app.job.GlueSimpleJob -1 className=sample.job.SamplePgm@S userKey=userData@S 042 * </xmp> 043 * </pre> 044 */ 045public class GlueSimpleJob 046{ 047 static ApplicationContext applicationContext = null; 048 static Logger logger = LoggerFactory.getLogger( GlueSimpleJob.class ); 049 050 public static void main( String args[] ) 051 { 052 logger.info( "GlueSimpleJob version : {}", JobConstants.VERSION ); 053 boolean isLocalTest = args != null && args.length > 0 && args[0] != null && "-1".equals( args[0] ); 054 if ( !isLocalTest ) 055 { 056 BasicDataSource dataSource = null; 057 Connection connection = null; 058 try 059 { 060 applicationContext = new ClassPathXmlApplicationContext( "applicationContext-job.xml" ); 061 dataSource = applicationContext.getBean( "dataSource", BasicDataSource.class ); 062 connection = DataSourceUtils.getConnection( dataSource ); 063 String databaseProductName = connection.getMetaData().getDatabaseProductName().toLowerCase(); 064 if ( databaseProductName.contains( "oracle" ) ) 065 { 066 dataSource.addConnectionProperty( "v$session.program", "GlueSimpleJob ver." + JobConstants.VERSION ); 067 // dataSource.addConnectionProperty( "v$session.process", "GlueSimpleJob-java" ); 068 // dataSource.addConnectionProperty( "v$session.terminal", "GlueSimpleJob-terminal" ); 069 // dataSource.addConnectionProperty( "v$session.client_info", "GlueSimpleJob-client" ); 070 } else if ( databaseProductName.contains( "postgresql" ) || databaseProductName.contains( "enterprisedb" ) ) 071 { 072 dataSource.addConnectionProperty( "ApplicationName", "GlueSimpleJob ver." + JobConstants.VERSION ); 073 } else 074 { 075 logger.warn( "not support adding datasource connection property (application name) - {}", databaseProductName ); 076 } 077 078 } catch ( Exception e ) 079 { 080 logger.error( "Exception", e ); 081 e.printStackTrace(); 082 return; 083 } catch ( Throwable t ) 084 { 085 logger.error( "Throwable", t ); 086 t.printStackTrace(); 087 return; 088 } finally 089 { 090 DataSourceUtils.releaseConnection( connection, dataSource ); 091 } 092 } 093 094 String name = ManagementFactory.getRuntimeMXBean().getName(); 095 String pid = name.substring( 0, name.indexOf( "@" ) ); 096 logger.info( "RuntimeMXBean Name : {}, {}", name, pid ); 097 if ( logger.isTraceEnabled() ) 098 { 099 logger.trace( "BootClassPath : {}", ManagementFactory.getRuntimeMXBean().getBootClassPath() ); 100 logger.trace( "ClassPath : {}", ManagementFactory.getRuntimeMXBean().getClassPath() ); 101 logger.trace( "LibraryPath : {}", ManagementFactory.getRuntimeMXBean().getLibraryPath() ); 102 logger.trace( "ManagementSpecVersion : {}", ManagementFactory.getRuntimeMXBean().getManagementSpecVersion() ); 103 logger.trace( "SpecName : {}", ManagementFactory.getRuntimeMXBean().getSpecName() ); 104 logger.trace( "SpecVendor : {}", ManagementFactory.getRuntimeMXBean().getSpecVendor() ); 105 logger.trace( "SpecVersion : {}", ManagementFactory.getRuntimeMXBean().getSpecVersion() ); 106 logger.trace( "StartTime : {}", ManagementFactory.getRuntimeMXBean().getStartTime() ); 107 logger.trace( "Uptime : {}", ManagementFactory.getRuntimeMXBean().getUptime() ); 108 logger.trace( "VmName : {}", ManagementFactory.getRuntimeMXBean().getVmName() ); 109 logger.trace( "VmVendor : {}", ManagementFactory.getRuntimeMXBean().getVmVendor() ); 110 logger.trace( "VmVersion : {}", ManagementFactory.getRuntimeMXBean().getVmVersion() ); 111 logger.trace( "SystemProperties : {}", ManagementFactory.getRuntimeMXBean().getSystemProperties() ); 112 logger.trace( "BootClassPathSupported : {}", ManagementFactory.getRuntimeMXBean().isBootClassPathSupported() ); 113 logger.trace( "InputArguments : {}", ManagementFactory.getRuntimeMXBean().getInputArguments() ); 114 List<String> arguements = ManagementFactory.getRuntimeMXBean().getInputArguments(); 115 for ( String string : arguements ) 116 { 117 logger.trace( "InputArgument : {}", string ); 118 } 119 } 120 if ( !isLocalTest ) 121 GlueSimpleJob.updateStartTime( args[0], pid ); 122 long start = System.currentTimeMillis(); 123 GlueContext ctx = new GlueDefaultContext(); 124 String requestId = null; 125 try 126 { 127 requestId = args[0]; 128 if ( logger.isTraceEnabled() ) 129 { 130 Map<String, String> env = System.getenv(); 131 logger.trace( "{}", env ); 132 logger.trace( "" ); 133 logger.trace( "{}", System.getProperties() ); 134 logger.trace( "" ); 135 logger.trace( "" ); 136 } 137 138 logger.info( "RequestID:[{}] StartTime[{}]", requestId, new Date( start ) ); 139 140 ctx.put( JobConstants.JOB_REQUEST_ID, requestId ); 141 142 for ( int i = 1; i < args.length; i++ ) 143 { 144 String arg = args[i]; 145 logger.trace( "{}", arg ); 146 // K:Keyword;S:String;B:boolean;I:Integer;L:Long;D:Double;F:Float 147 if ( arg.contains( "=" ) ) 148 { 149 String s[] = arg.split( "=" ); 150 if ( arg.startsWith( "\"" ) && arg.endsWith( "\"" ) ) 151 { 152 String tmp = arg.substring( 1, arg.length() - 1 ); 153 logger.trace( "{}", tmp ); 154 s = tmp.split( "=" ); 155 } 156 if ( s[1].contains( "@" ) ) 157 { 158 int idx = s[1].lastIndexOf( "@" ); 159 String value = s[1].substring( 0, idx ); 160 if ( s[1].endsWith( "S" ) ) 161 { 162 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? "" : value ); 163 } else if ( s[1].endsWith( "B" ) ) 164 { 165 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : Boolean.valueOf( value ) ); 166 } else if ( s[1].endsWith( "I" ) ) 167 { 168 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Integer( value ) ); 169 } else if ( s[1].endsWith( "L" ) ) 170 { 171 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Long( value ) ); 172 } else if ( s[1].endsWith( "D" ) ) 173 { 174 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Double( value ) ); 175 } else if ( s[1].endsWith( "F" ) ) 176 { 177 ctx.put( s[0], "NULL".equalsIgnoreCase( value ) ? null : new Float( value ) ); 178 } 179 } else 180 { 181 ctx.put( s[0], s[1] ); 182 } 183 } else 184 { 185 logger.error( "ignore {}", arg ); 186 } 187 } 188 logger.info( "{}", ctx ); 189 190 if ( ctx.containsKey( GlueBizControlConstants.SERVICE_NAME ) ) 191 { 192 try 193 { 194 GlueBizProvider.getController().doAction( ctx ); 195 } catch ( Throwable t ) 196 { 197 if ( ctx.getException() != null ) 198 { 199 // BeanCreationException 등 GlueService 실행 전에 발생된 에러를 처리하기 위함. 200 ctx.setException( t ); 201 } else 202 { 203 logger.error( "unknwon error", t ); 204 } 205 t.printStackTrace(); 206 } 207 } else if ( ctx.containsKey( "className" ) ) 208 { 209 try 210 { 211 Object clz = Thread.currentThread().getContextClassLoader().loadClass( (String) ctx.get( "className" ) ).newInstance(); 212 Method method = clz.getClass().getMethod( "runProgram", new Class[] { GlueContext.class } ); 213 method.invoke( clz, new Object[] { ctx } ); 214 if ( ctx.getException() != null ) 215 { 216 logger.error( "UserException", ctx.getException() ); 217 ctx.getException().printStackTrace(); 218 } 219 // ctx.getException(); 220 } catch ( InstantiationException e ) 221 { 222 ctx.setException( e ); 223 logger.error( "InstantiationException", e ); 224 } catch ( IllegalAccessException e ) 225 { 226 ctx.setException( e ); 227 logger.error( "IllegalAccessException", e ); 228 } catch ( ClassNotFoundException e ) 229 { 230 ctx.setException( e ); 231 logger.error( "ClassNotFoundException", e ); 232 } catch ( SecurityException e ) 233 { 234 ctx.setException( e ); 235 logger.error( "SecurityException", e ); 236 } catch ( NoSuchMethodException e ) 237 { 238 ctx.setException( e ); 239 logger.error( "NoSuchMethodException", e ); 240 } catch ( IllegalArgumentException e ) 241 { 242 ctx.setException( e ); 243 logger.error( "IllegalArgumentException", e ); 244 } catch ( InvocationTargetException e ) 245 { 246 ctx.setException( e ); 247 logger.error( "InvocationTargetException", e ); 248 } catch ( Throwable t ) 249 { 250 ctx.setException( t ); 251 logger.error( "UserException", t ); 252 } 253 } else 254 { 255 ctx.setException( new Exception( "Service is Null!" ) ); 256 logger.info( "Service is Null!" ); 257 } 258 259 } catch ( Exception e ) 260 { 261 logger.error( "Exception", e ); 262 e.printStackTrace(); 263 } catch ( Throwable t ) 264 { 265 logger.error( "Throwable", t ); 266 t.printStackTrace(); 267 } finally 268 { 269 long end = System.currentTimeMillis(); 270 if ( !isLocalTest ) 271 GlueSimpleJob.updateEndTime( args[0], end - start, ctx.getException() ); 272 logger.info( "RequestID:[{}] EndTime[{}] RunTime:[{}]", requestId, new Date( end ), end - start ); 273 } 274 System.exit( 0 ); 275 } 276 277 private static void updateEndTime( String id, long runtime, Throwable throwable ) 278 { 279 try 280 { 281 if ( "-1".equals( id ) ) 282 { 283 return; 284 } 285 DataSource ds = applicationContext.getBean( "dataSource", DataSource.class ); 286 logger.debug( "{}", JobConstants.SQL_PGM_END ); 287 logger.trace( "{}", runtime ); 288 logger.trace( "{}", throwable == null ? "END" : "ERROR" ); 289 logger.trace( "{}", id ); 290 Connection con = null; 291 PreparedStatement ps = null; 292 con = DataSourceUtils.getConnection( ds ); 293 try 294 { 295 ps = con.prepareStatement( JobConstants.SQL_PGM_END ); 296 ps.setObject( 1, runtime ); 297 ps.setObject( 2, throwable == null ? "END" : "ERROR" ); 298 ps.setObject( 3, new Long( id ) ); 299 ps.executeUpdate(); 300 con.commit(); 301 } catch ( SQLException e ) 302 { 303 logger.error( "fail to executeUpdate", e ); 304 } finally 305 { 306 JdbcUtils.closeStatement( ps ); 307 DataSourceUtils.releaseConnection( con, ds ); 308 } 309 } catch ( Exception e ) 310 { 311 logger.error( "fail to getConnection", e ); 312 } catch ( Throwable t ) 313 { 314 logger.error( "fail to getConnection", t ); 315 } 316 } 317 318 private static void updateStartTime( String id, String pid ) 319 { 320 try 321 { 322 if ( "-1".equals( id ) ) 323 { 324 return; 325 } 326 DataSource ds = applicationContext.getBean( "dataSource", DataSource.class ); 327 logger.debug( "{}", JobConstants.SQL_PGM_START ); 328 logger.trace( "{}", "RUNNING" ); 329 logger.trace( "{}", pid ); 330 logger.trace( "{}", id ); 331 332 Connection con = null; 333 PreparedStatement ps = null; 334 con = DataSourceUtils.getConnection( ds ); 335 try 336 { 337 ps = con.prepareStatement( JobConstants.SQL_PGM_START ); 338 ps.setObject( 1, "RUNNING" ); 339 ps.setObject( 2, new Integer( pid ) ); 340 ps.setObject( 3, new Long( id ) ); 341 ps.executeUpdate(); 342 con.commit(); 343 } catch ( SQLException e ) 344 { 345 logger.error( "fail to executeUpdate", e ); 346 } catch ( Exception e ) 347 { 348 logger.error( "fail to getConnection", e ); 349 } catch ( Throwable t ) 350 { 351 logger.error( "fail to getConnection", t ); 352 } finally 353 { 354 JdbcUtils.closeStatement( ps ); 355 DataSourceUtils.releaseConnection( con, ds ); 356 } 357 } catch ( Exception e ) 358 { 359 logger.error( "fail to getConnection", e ); 360 } catch ( Throwable t ) 361 { 362 logger.error( "fail to getConnection", t ); 363 } 364 } 365}