2010. 4. 28 오후 10:06:26 org.apache.jk.core.MsgContext action
경고: Error sending end packet
java.net.SocketException: Broken pipe
 at java.net.SocketOutputStream.socketWrite0(Native Method)
 at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
 at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
 at org.apache.jk.common.ChannelSocket.send(ChannelSocket.java:537)
 at org.apache.jk.common.JkInputStream.endMessage(JkInputStream.java:127)
 at org.apache.jk.core.MsgContext.action(MsgContext.java:302)
 at org.apache.coyote.Response.action(Response.java:183)
 at org.apache.coyote.Response.finish(Response.java:305)
 at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:205)
 at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:283)
 at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:773)
 at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:703)
 at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:895)
 at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:685)
 at java.lang.Thread.run(Thread.java:619)
2010. 4. 28 오후 10:06:26 org.apache.jk.common.ChannelSocket processConnection
경고: processCallbacks status 2

특정상황에서 위와같은 로그가 찍힐때가 있다.. (F5연타로 인한 Client Abort와는 다름)

단독 Tomcat 으로 돌릴때는 위와같은 오류가 전혀 없었다.. (8080포트로 접속했을때)

Apache 2.2, Tomcat 5.5 mod_jk2 연동후 80포트로 접속했을때 위와같은 로그가 찍혔다..

또한 파이어폭스, 크롬등의 브라우저로 접속했을때는 아무런 로그가 찍히지 않고

IE로 접속했을때만 위의 로그가 찍혔다..ㅡㅡ;


결론은 <img src="" /> 때문이었다..    빈.. 이미지 태그를 제거하니 아무런 로그도 찍히지 않았다..

서버단 처리중에 클라이언트가 강제로 요청을 취소, 연결이 끊어질 경우라고 하는데..

이유는 역시나 잘 모르겠다..



아래와같은 이유때문에 발생할수도 있다 (이중 서브밋)
http://javanuri.co.kr/devforum/boardView.jsp?pg=2&menuId=12&Id=306220&gb=qna



Posted by 알 수 없는 사용자 :
 영문을 개념없이 ssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssss
이렇게 쭉~~ 붙여서 치면 width 밖으로 삐져나가게 되는데

style="text-overflow: clip; overflow: hidden; word-break: break-all;";

넣어주면 IE6 7 8, FF 에서 모두 문제없이 줄바꿈 됨.
 word-break: break-all; 은 비표준 태그라고 하는데..
IE에서 다른방법은 모르겠으니 일단 패스..;
Posted by 알 수 없는 사용자 :
커스텀 Ajax Loader 이미지 만들어주는곳

http://www.ajaxload.info/

사이트 디자인에따라 적절한 Ajax Loader 이미지를 만들수 있다.

색상, 디자인, 투명배경 여부 등등.






Posted by 알 수 없는 사용자 :
시작일, 종료일 yyyy-MM-dd 형식으로 입력받아서 검색할때 그대~로 쓰시면 됩니다.
if( UtilBean.isValidDate(formattype, startdate) || UtilBean.isValidDate(formattype, enddate) ) {
          /*등록일 검색*/
         
          SimpleDateFormat sdf = new SimpleDateFormat(formattype);
          boolean isDuration = ( UtilBean.isValidDate(formattype, startdate) && UtilBean.isValidDate(enddate, formattype) );
          bWhere.append(" and ");
          if( isDuration ){
          bWhere.append(" ( ");
          }
          if( UtilBean.isValidDate(formattype, startdate) ){
            bWhere.append("A.CREATEDON >= to_date('").append(startdate).append("', '").append( formattype.toUpperCase() ).append("') ");
          }
          if( isDuration ){
            bWhere.append(" and ");
          }
          if( UtilBean.isValidDate(formattype, enddate) ){
            bWhere.append("A.CREATEDON < to_date('").append( sdf.format(new java.util.Date( sdf.parse(enddate).getTime()+( 1000 * 24 * 3600 ))) ).append("', '").append( formattype.toUpperCase() ).append("') ");
          }
          if( isDuration ){
          bWhere.append(" ) ");
          }
        }

String sWhere = bWhere.toString().replaceFirst("(?i)and", "");

/* 이건 catch 말고 답없음. */
  public static boolean isValidDate( SimpleDateFormat sdf, String date ) {
    try{
      sdf.parse(date);
    }catch(ParseException e){
      return false;
    }
    return true;
  }



Posted by 윤재현 :

JQUERY ANIMATE활용

2009. 8. 10. 14:47 from JAVASCRIPT
http://buildinternet.com/live/boxes/
알아두면 기획서 극복에 도움이 됩니다.

http://flowplayer.org/tools/demos/overlay/styling.html
UI관련 라이브러리들 모음
Posted by 윤재현 :

Quartz로 데몬돌리기

2009. 8. 10. 00:00 from JSP
우선 소스까지 떠다먹여주신 개발자분에 대한 감사와 존경의 마음을 담아 링크를 걸고
http://blog.naver.com/an5asis/60019595888

부족한 구현능력을 커버해주는 오픈소스개발자들의 산출물에 다시한번 링크를,,,
http://www.opensymphony.com/quartz/

쿼츠 최신버전인 quartz-1.6.5.zip 를 다운받아 압축을 풀면
폴더 최상위에
quartz-1.6.5.jar

lib/core 에 있는

commons-collections-3.2.jar
commons-logging-1.1.jar

파일을 각각 참조 라이브러리에 등록합니다.

억지로 읽게 하려고 의미없는 사진도 첨부합니다.

  1. package q;  
  2. import org.quartz.CronTrigger;  
  3. import org.quartz.JobDetail;  
  4. import org.quartz.Scheduler;  
  5. import org.quartz.SchedulerFactory;  
  6. public class InfinityQuartz {  
  7.   public static void main(String[] args) {  
  8.     try {  
  9.       SchedulerFactory schedFact = new org.quartz.impl.StdSchedulerFactory();  
  10.       Scheduler sched = schedFact.getScheduler();  
  11.       sched.start();  
  12.       JobDetail jobDetail = new JobDetail("Income Report""Report Generation", QuartzReport.class);  
  13.       jobDetail.getJobDataMap().put("type","FULL"); //필요 없을수 있음. 파라메터 전달할 경우만 사용  
  14.       CronTrigger trigger = new CronTrigger("Income Report","Report Generation");  
  15.       trigger.setCronExpression("0/20 * * * * ?");  
  16.       sched.scheduleJob(jobDetail, trigger);  
  17.     } catch (Exception e) {  
  18.       e.printStackTrace();  
  19.     }  
  20.   }  
  21. }  
위 부분이 스케줄을 실행할 메인함수인데 간단합니다. JobDetail 생성자 부분의 세번째 인자인 QuartzReport.class 의 execute 함수를 trigger.setCronExpression의 양식에 맞게 스케쥴링 하는게 끝이죠 부가적으로 getJobDataMap().put("type", "FULL")은 파라메터맵 설정하는정도로 생각하시면 됩니다.
  1. package q;  
  2. import org.quartz.*;  
  3. public class QuartzReport implements Job {  
  4.   public void execute(JobExecutionContext cntxt)throws JobExecutionException {  
  5.     System.out.println("Generating report - " + cntxt.getJobDetail().getJobDataMap().get("type")); //이줄만 원하는대로 고치면 땡 현재는 파라메터맵에서 type값을 출력.  
  6.   }  
  7. }  
결론적으로 위에있는 소스중에 execute만 고쳐서 쓰세요.
Posted by 윤재현 :
아 무슨 서버도 없어서 이런 링크를 ,,
데모
Posted by 윤재현 :
주기적으로 디비에 어떤 데이터를 쌓거나 시간대별로 특정한 작업을하려면 데몬을 돌려야 하는데
간단하게 사용할수 있는 데몬입니다.

0. 쿼츠 다운로드 : http://www.opensymphony.com/quartz/download.action
다운로드 받고 안에있는 quartz-1.6.5.jar을 라이브러리에 추가
  
1. 서버 구동시 자동으로 쿼츠가 실행되도록 WEB-INF/web.xml 에 추가  (quartz.properties, SchedulerInit.java 경로확인!!)
  1. <!-- Quartz 로딩부분  -->    
  2.     
  3.   <servlet>  
  4.     <display-name>Quartz Initializer Servlet</display-name>  
  5.     <servlet-name>QuartzInitializer</servlet-name>  
  6.     <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>  
  7.     <init-param>  
  8.       <param-name>config-file</param-name>  
  9.       <param-value>com/ineast/scheduler/quartz.properties</param-value>  
  10.     </init-param>  
  11.     <init-param>  
  12.       <param-name>shutdown-on-unload</param-name>  
  13.       <param-value>true</param-value>  
  14.     </init-param>  
  15.     <init-param>  
  16.       <param-name>start-scheduler-on-load</param-name>  
  17.       <param-value>true</param-value>  
  18.     </init-param>  
  19.     <load-on-startup>1</load-on-startup>  
  20.   </servlet>  
  21.     
  22.   <servlet>  
  23.     <display-name>SchedulerInit</display-name>  
  24.     <servlet-name>SchedulerInit</servlet-name>  
  25.     <servlet-class>com.ineast.scheduler.SchedulerInit</servlet-class>  
  26.     <load-on-startup>2</load-on-startup>  
  27.   </servlet>  
  28.   <servlet-mapping>  
  29.     <servlet-name>SchedulerInit</servlet-name>  
  30.     <url-pattern>/SchedulerInit</url-pattern>  
  31.   </servlet-mapping>  
  32.     

2.quartz.properties
 
  1. org.quartz.scheduler.instanceName = SchedulerInit  
  2. org.quartz.scheduler.instanceId = AUTO  
  3. org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool  
  4. org.quartz.threadPool.threadCount = 12  
  5. org.quartz.threadPool.threadPriority = 5  
  6. org.quartz.jobStore.misfireThreshold = 60000  
  7. org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore  


3. 이니셜라이저 부분 ( SchedulerInit.java )
  1. package com.ineast.scheduler;  
  2.   
  3. import java.text.ParseException;  
  4. import org.quartz.CronTrigger;  
  5. import org.quartz.JobDetail;  
  6. import org.quartz.Scheduler;  
  7. import org.quartz.SchedulerException;  
  8. import org.quartz.SchedulerFactory;  
  9. import org.quartz.impl.StdSchedulerFactory;  
  10.   
  11. public class SchedulerInit {  
  12.   private SchedulerFactory schedFact;  
  13.   private Scheduler sched;  
  14.   
  15.   public SchedulerInit() {  
  16.     try {  
  17.       schedFact = new StdSchedulerFactory();  
  18.       sched = schedFact.getScheduler();  
  19.       sched.start();  
  20.   
  21.        //"job이름, 그룹명, 동작시킬Class"  
  22.       JobDetail job1 = new JobDetail("Job_MyAlarmData1""group1", Job_MyAlarmData.class);   
  23.        // 매분 0초에 동작(30초마다 동작시키려면 job을 하나더 만들고 아래에 0대신 30을 넣으면 ok  
  24.       CronTrigger trigger1 = new CronTrigger("Trigger_MyAlarmData1""group1""0 * * * * ?");   
  25.       sched.scheduleJob(job1, trigger1);  
  26.         
  27.     } catch (SchedulerException e) {  
  28.       e.printStackTrace();  
  29.     } catch (ParseException e) {  
  30.       e.printStackTrace();  
  31.     }  
  32.   }  
  33.   
  34.   public static void main(String[] args) {  
  35.     new SchedulerInit();  
  36.   }  
  37. }  


4. 사용자 로직부분
  1. package com.ineast.scheduler;  
  2.   
  3. import java.util.Hashtable;  
  4. import java.util.Vector;  
  5. import com.ineast.common.DbParent;  
  6. import com.ineast.common.UtilBean;  
  7. import personal.MyAlarmBean;  
  8. import java.util.Date;  
  9.   
  10. import org.quartz.Job;  
  11. import org.quartz.JobExecutionContext;  
  12. import org.quartz.JobExecutionException;  
  13.   
  14. public class Job_MyAlarmData extends DbParent implements Job { //DbParent상속받은 상태  
  15.     
  16.   public void execute(JobExecutionContext context) throws JobExecutionException {  
  17.     getMyAlarmData(); //이부분에 로직을 작성  
  18.   }  
  19.     
  20.   public void getMyAlarmData() {  
  21.      System.out.println("우왕ㅋ굳ㅋ");  
  22.   }  
  23.     
  24. }  


Job이 DB에서 읽어온값을 Bean에있는 Static Hashtable에 주기적으로 업데이트 시킬 필요가 있었는데
Static 객체에 바로 접근이 가능한걸보니 WAS프로세스 안에서 돌아가는 것으로 보인다.


작업주기 설정하는건 아래링크에보시면 있음~
http://blog.naver.com/kjh28480?Redirect=Log&logNo=70048565972
Posted by 알 수 없는 사용자 :
http://www.jankoatwarpspeed.com/examples/reinventing-drop-down/

/* dt 클릭시 하위 국가리스트 show/hide */
$(".dropdown dt a").click(function() {
$(".dropdown dd ul").toggle();
});

/* 이부분은 dropdown dd 의 display를 검사해서 수행하도 될듯한데 여기서는 이벤트발생객체의 parent를 검사함 */
$(document).bind('click', function(e) {
var $clicked = $(e.target);
if (! $clicked.parents().hasClass("dropdown"))
$(".dropdown dd ul").hide(); //펼치기에 방해 안되도록 dropdown 외부를 클릭했으면 hide
});
/* 하위국가리스트 선택시 액션이므로 첫줄만 보면 되겠음 .click, $(".dropdown dd ul").hide() */
$(".dropdown dd ul li a").click(function() {
var text = $(this).html();
$(".dropdown dt a span").html(text);
$(".dropdown dd ul").hide();
$("#result").html("Selected value is: " + getSelectedValue("sample"));
});
요새 트위트로 소스들좀 받고있는데 고작이런거나 쓸정도로 허접한것들만 올라와서 이거라도 올림. 우리 코딩팀에도 요건 좀 전달해야할듯 IE6에서 셀렉트박스가 다른객체위로 떡하니 올라가는 현상때문에..
Posted by 윤재현 :
간만에 대형 월척을 낚았다.

현재 페이징 쿼리를 만들어주는 메서드를 보면

       buffer.append("select * from (select rownum as row_num, ")
              .append(getRemoveAlias(tblField))
              .append(" from (select ")
              .append(tblField)
              .append(" from ")
              .append(tblName);
        if(wh!=null && wh.length()>0) {
          buffer.append(" where ")
                .append(wh);
        }       
        buffer.append(" order by ")
              .append(ob);
        if(isDesc) buffer.append(" desc)) ");
        else buffer.append(" asc)) ");
        buffer.append(" where row_num <= ")
              .append((currentPage)*pageSize)
              .append(" and row_num > ")
              .append((currentPage-1)*pageSize);


와 같이 가져온다.

간단히 말해 안쪽에 있는 쿼리에서 데이터를 전부 가져와서는 맨 바깥에서 row_num 으로 페이지를 자른다.
이렇게 되면 문제가 테이블에서 건수가 100만건이라 가정하면 100만건에 대해 전부 select 해서 rownum 을 전부 매겨서 맨 마지막에 페이지를 자르니, 부하가 많아져서 쿼리 속도가 엄청 늦다.

이렇게 하면 안되고, 안쪽에서 미리 페이지 수에 맞는 만큼( 1페이지면 10개, 2페이지면 20개 등 ) 가져오고 마지막에 row_num 으로 잘라준다.

       buffer.append("select * from (select rownum as row_num, ")
              .append(getRemoveAlias(tblField))
              .append(" from (select ")
              .append(tblField)
              .append(" from ")
              .append(tblName);
        buffer.append(" where rownum <= ")
              .append((currentPage)*pageSize);
        if(wh!=null && wh.length()>0) {
          buffer.append(" and ")
                .append(wh);
        }       
        buffer.append(" order by ")
              .append(ob);
        if(isDesc) buffer.append(" desc)) ");
        else buffer.append(" asc)) ");
        buffer.append(" where row_num > ")
              .append((currentPage-1)*pageSize);


이렇게 수정해준다. 라고 생각하면 큰 오산이다.
왜냐면, rownum 은 select 를 해오고, sort 를 하기전에 붙여진다. 즉 위처럼 하면 order by 하기전에 임의로 rownum 이 붙여지고는 order by 된다.

따라서

       buffer.append("select * from (select rownum as row_num, ")
              .append(getRemoveAlias(tblField))
              .append(" from (select ")
              .append(tblField)
              .append(" from ")
              .append(tblName);       
        if(wh!=null && wh.length()>0) {
          buffer.append(" where ")
                .append(wh);
        }       
        buffer.append(" order by ")
              .append(ob);
        if(isDesc) buffer.append(" desc) ");
        else buffer.append(" asc) ");
        buffer.append(" where rownum <= ")
              .append((currentPage)*pageSize)
              .append(" ) ");
       
        buffer.append(" where row_num > ")
              .append((currentPage-1)*pageSize);


이렇게 수정해준다.

"아니 이렇게 하면 전체를 order by 할 때 비용이 많이 들지 않냐"고 궁금해하면 훌륭하다!
order by 되는 곳에 index를 적절히 걸어주면 되고, 맨 안쪽에서 select 를 할 때 그 인덱스를 타기 때문에 성능은 그리 떨어지지 않는다.

참고할만한 페이지는
http://www.oracle.com/technology/global/kr/oramag/oracle/06-sep/o56asktom.html
에 있다.


Posted by 알 수 없는 사용자 :