1.JMS
JAVA æ¶ˆæ¯æœåŠ¡(JMS)定义了Java ä¸è®¿é—®æ¶ˆæ¯ä¸é—´äšg的接å£ã€‚JMS åªæ˜¯æŽ¥å£åQŒåƈ没有¾l™äºˆå®žçްåQŒå®žçްJMS 接å£çš„æ¶ˆæ¯ä¸é—´äšg¿UîCØ“JMS ProvideråQŒiLink实现了JMS接å£åQŒç”¨æˆ·å¯ä»¥é€šè¿‡ä½¿ç”¨JMS接å£åQŒåœ¨iLinkä¸è¿›è¡ŒJMS¾~–程ã€?iLink支æŒJMS1.0.2版本ã€?
2.JMSæŽ¥å£æè¿°
JMS 支æŒä¸¤ç§æ¶ˆæ¯¾cÕdž‹PTP å’ŒPub/SubåQŒåˆ†åˆ«ç§°ä½œï¼šPTP Domain å’ŒPub/Sub DomainåQŒè¿™ä¸¤ç§æŽ¥å£éƒ½ç‘ô承统一的JMS父接å£ï¼ŒJMS ä¸»è¦æŽ¥å£å¦‚下所½Cºï¼š
|
ConnectionFactory åQšè¿žæŽ¥å·¥åŽ‚ï¼ŒJMS 用它创徘qžæŽ¥
Connection åQšJMS 客户端到JMS Provider 的连æŽ?br> Destination åQšæ¶ˆæ¯çš„目的åœ?br> SessionåQ?一个å‘逿ˆ–接收消æ¯çš„线½E?br> MessageProduceråQ?ç”±Session 对象创å¾çš„用æ¥å‘逿¶ˆæ¯çš„对象
MessageConsumeråQ?ç”±Session 对象创å¾çš„ç”¨æ¥æŽ¥æ”¶æ¶ˆæ¯çš„对象
3.JMSæ¶ˆæ¯æ¨¡åž‹
JMS 消æ¯ç”׃»¥ä¸‹å‡ 部分¾l„æˆåQšæ¶ˆæ¯å¤´åQŒå±žæ€§ï¼Œæ¶ˆæ¯ä½“ã€?br>
3.1 消æ¯å¤?Header) - 消æ¯å¤´åŒ…嫿¶ˆæ¯çš„识别信æ¯å’Œèµ\ç”׃¿¡æ¯ï¼Œæ¶ˆæ¯å¤´åŒ…å«ä¸€äº›æ ‡å‡†çš„属性如åQšJMSDestination,JMSMessageID ½{‰ã€?
|
3.2 属æ€?Properties) - 除了消æ¯å¤´ä¸å®šä¹‰å¥½çš„æ ‡å‡†å±žæ€§å¤–åQŒJMS æä¾›ä¸€¿Uæœºåˆ¶å¢žåŠ æ–°å±žæ€§åˆ°æ¶ˆæ¯å¤?ä¸ï¼Œ˜q™ç§æ–°å±žæ€§åŒ…å«ä»¥ä¸‹å‡ ¿U:
1. 应用需è¦ç”¨åˆ°çš„属æ€?
2. 消æ¯å¤´ä¸åŽŸæœ‰çš„ä¸€äº›å¯é€‰å±žæ€?
3. JMS Provider 需è¦ç”¨åˆ°çš„属性ã€?br> æ ‡å‡†çš„JMS 消æ¯å¤´åŒ…å«ä»¥ä¸‹å±žæ€§ï¼š
|
3.3 消æ¯ä½?Body) - JMS API 定义äº?¿U消æ¯ä½“æ ¼å¼åQŒä¹Ÿå«æ¶ˆæ¯ç±»åž‹ï¼Œä½ å¯ä»¥ä‹É用ä¸åŒåÅžå¼å‘逿ޥæ”?æ•°æ®òq¶å¯ä»¥å…¼å®¹çŽ°æœ‰çš„æ¶ˆæ¯æ ¼å¼åQŒä¸‹é¢æ˜q°è¿™5¿U类型:
|
下例演示创å¾òq¶å‘é€ä¸€ä¸ªTextMessageåˆîC¸€ä¸ªé˜Ÿåˆ—:
TextMessage message = queueSession.createTextMessage();
message.setText(msg_text); // msg_text is a String
queueSender.send(message);
下例演示接收消æ¯òq¶è{æ¢äØ“åˆé€‚的消毾cÕdž‹åQ?
Message m = queueReceiver.receive();
if (m instanceof TextMessage) {
TextMessage message = (TextMessage) m;
System.out.println("Reading message: " + message.getText());
} else {
// Handle error
}
4. 消æ¯çš„åŒæ¥å¼‚æ¥æŽ¥æ”?br> 消æ¯çš„åŒæ¥æŽ¥æ”¶æ˜¯æŒ‡å®¢æˆïL«¯ä¸ÕdЍåŽÀLŽ¥æ”¶æ¶ˆæ¯ï¼ŒJMS 客户端å¯ä»¥é‡‡ç”¨MessageConsumer çš„receiveæ–ÒŽ³•åŽÀLŽ¥æ”¶ä¸‹ä¸€ä¸ªæ¶ˆæ¯ã€?br> 消æ¯çš„å¼‚æ¥æŽ¥æ”¶æ˜¯æŒ‡å½“æ¶ˆæ¯åˆ°è¾¾æ—Óž¼Œä¸ÕdŠ¨é€šçŸ¥å®¢æˆ·ç«¯ã€‚JMS 客户端å¯ä»¥é€šè¿‡æ³¨å†Œä¸€ä¸ªå®ž 现MessageListener 接å£çš„对象到MessageConsumeråQŒè¿™æ øP¼Œæ¯å½“消æ¯åˆ°è¾¾æ—Óž¼ŒJMS Provider 会调用MessageListenerä¸çš„onMessage æ–ÒŽ³•ã€?
5. PTP模型
PTP(Point-to-Point)模型是基于队列的åQŒå‘逿–¹å‘消æ¯åˆ°é˜Ÿåˆ—åQŒæŽ¥æ”¶æ–¹ä»Žé˜Ÿåˆ—接收消æ¯ï¼Œé˜Ÿåˆ—çš„å˜åœ¨ä‹É得消æ¯çš„异æ¥ä¼ 输æˆäØ“å¯èƒ½ã€‚和邮äšg¾pÈ»Ÿä¸çš„é‚®ç®±ä¸€æ øP¼Œé˜Ÿåˆ—å¯ä»¥åŒ…å«å„ç§æ¶ˆæ¯åQŒJMS Provider æ?供工å…ïL®¡ç†é˜Ÿåˆ—的创å¾ã€åˆ 除。JMS PTP 模型定义了客æˆïL«¯å¦‚何å‘队列å‘逿¶ˆæ¯ï¼Œä»Žé˜Ÿåˆ—接收消æ¯ï¼Œ‹¹è§ˆé˜Ÿåˆ—ä¸çš„æ¶ˆæ¯ã€?br> ä¸‹é¢æè¿°JMS PTP 模型ä¸çš„ä¸»è¦æ¦‚念和对象:
|
6. PUB/SUB模型
JMS Pub/Sub 模型定义了如何å‘一个内容节点å‘布和订阅消æ¯åQŒè¿™äº›èŠ‚ç‚¹è¢«¿UîC½œä¸»é¢˜(topic)ã€?br> 主题å¯ä»¥è¢«è®¤ä¸ºæ˜¯æ¶ˆæ¯çš„ä¼ è¾“ä¸ä»‹ï¼Œå‘布è€?publisher)å‘布消æ¯åˆîC¸»é¢˜ï¼Œè®¢é˜…è€?subscribe)从主题订阅消æ¯ã€‚主题ä‹É得消æ¯è®¢é˜…者和消æ¯å‘å¸ƒè€…ä¿æŒäº’相独立,ä¸éœ€è¦æŽ¥è§¦å³å¯ä¿è¯æ¶ˆæ¯çš„ä¼ é€ã€?br> ä¸‹é¢æè¿°JMS Pub/Sub 模型ä¸çš„ä¸»è¦æ¦‚念和对象:
|
7. å¼€å‘JMSçš„æ¥éª?br> òq¿ä¹‰ä¸Šè¯´åQŒä¸€ä¸ªJMS åº”ç”¨æ˜¯å‡ ä¸ªJMS å®¢æˆ·ç«¯äº¤æ¢æ¶ˆæ¯ï¼Œå¼€å‘JMS å®¢æˆ·ç«¯åº”ç”¨ç”±ä»¥ä¸‹å‡ æ¥æž„æˆåQ?
用JNDI 得到ConnectionFactory 对象åQ?
用JNDI å¾—åˆ°ç›®æ ‡é˜Ÿåˆ—æˆ–ä¸»é¢˜å¯¹è±¡ï¼Œå³Destination 对象åQ?
用ConnectionFactory 创å¾Connection 对象åQ?
用Connection 对象创å¾ä¸€ä¸ªæˆ–多个JMS SessionåQ?
用Session å’ŒDestination 创å¾MessageProducer å’ŒMessageConsumeråQ?
通知Connection å¼€å§‹ä¼ é€’æ¶ˆæ¯ã€?/font>
<[ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Deployment descriptor "/WEB-INF/bhr-tags-pagination.tld" is malformed. Check against the DTD: Content is not allowed in prolog. (line 1, column 1).> <[ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Error while parsing the Tag Library Descriptor at "/WEB-INF/bhr-tags-pagination.tld". org.xml.sax.SAXException: [HTTP:101248][ServletContext(id=18489944,name=EBLGWeb,context-path=/)]: Deployment descriptor "/WEB-INF/bhr-tags-pagination.tld" is malformed. Check against the DTD: Content is not allowed in prolog. (line 1, column 1). at weblogic.apache.xerces.parsers.DOMParser.parse(DOMParser.java:285) at weblogic.apache.xerces.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:201) at weblogic.servlet.jsp.dd.JSPEntityResolver.load(JSPEntityResolver.java:81) at weblogic.servlet.jsp.dd.JSPEntityResolver.load(JSPEntityResolver.java:96) at weblogic.servlet.internal.WebAppHelper.registerTagLibListeners(WebAppHelper.java:293) at weblogic.servlet.internal.WebAppServletContext.activateFromDescriptors(WebAppServletContext.java:2530) at weblogic.servlet.internal.WebAppServletContext.activate(WebAppServletContext.java:6163) at weblogic.servlet.internal.WebAppServletContext.setActive(WebAppServletContext.java:6141) at weblogic.servlet.internal.WebAppModule.activate(WebAppModule.java:836) at weblogic.j2ee.J2EEApplicationContainer.activateModule(J2EEApplicationContainer.java:3322) at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2201) at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2174) at weblogic.j2ee.J2EEApplicationContainer.activate(J2EEApplicationContainer.java:2122) at weblogic.management.deploy.slave.SlaveDeployer$Application.setActivation(SlaveDeployer.java:3099) at weblogic.management.deploy.slave.SlaveDeployer.setActivationStateForAllApplications(SlaveDeployer.java:1768) at weblogic.management.deploy.slave.SlaveDeployer.resume(SlaveDeployer.java:351) at weblogic.management.deploy.DeploymentManagerServerLifeCycleImpl.resume(DeploymentManagerServerLifeCycleImpl.java:229) at weblogic.t3.srvr.SubsystemManager.resume(SubsystemManager.java:136) at weblogic.t3.srvr.T3Srvr.resume(T3Srvr.java:965) at weblogic.t3.srvr.T3Srvr.run(T3Srvr.java:360) at weblogic.Server.main(Server.java:32) >åŽŸå› åˆ†æžå’Œè§£å†Ïx–¹æ³?
是由于æŸäº›æ–‡æœ¬ç¼–辑器åQˆUltraEditåQ‰å˜æ–‡æœ¬çš„æ—¶å€™äñ”生的问题。å¯ä»¥ä‹É用text pad, word pad¾~–辑XMLæ ¼å¼çš„æ–‡ä»¶ã€?
通过HTTPæäº¤EDIè¯äh±‚,当EDIå¤„ç†æ—‰™—´‘…过äº?0分钟å?ž®×ƒ¼šçœ‹åˆ°åœ¨å¦ä¸€ä¸ªweblogic server也接收到了这个EDIè¯äh±‚,釿–°å¤„熘q™ä¸ªæŠ¥æ–‡. å¦‚æžœæŠ¥æ–‡å¤„ç†æ—‰™—´æ›´é•¿,比如‘…过äº?0分钟,ž®×ƒ¼šå‘现˜q™ä¸ªæŠ¥æ–‡è¢«å¤„ç†äº†3éæˆ–5é?åŽŸå› åˆ†æžå’Œè§£å†Ïx–¹æ³?
When the Apache HTTP Server Plug-In attempts to connect to WebLogic Server, the plug-in uses several configuration parameters to determine how long to wait for connections to the WebLogic Server host and, after a connection is established, how long the plug-in waits for a response. If the plug-in cannot connect or does not receive a response, the plug-in attempts to connect and send the request to other WebLogic Server instances in the cluster. If the connection fails or there is no response from any WebLogic Server in the cluster, an error message is sent. å“应½{‰å¾…æ—‰™—´å‚æ•°WLIOTimeoutSecs (http://e-docs.bea.com/wls/docs81/plugins/plugin_params.html#1149781. 按照BEA 推è的,˜q™ä¸ªå€¼åº”该设得大一äº? ˜q™ä¸ªå‚数的缺çœå€égØ“300s. è§ä¸‹é¢ï¼š <Location /EDIHandler> SetHandler weblogic-handler WebLogicCluster apc_app1wls1:7011,apc_app1wls2:7011 KeepAliveEnabled ON WLIOTimeoutSecs 7200 </Location>
MQJMS200713 Oct 2006 16:47:15,484 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: **********EXCEPTION TRACE START************* 13 Oct 2006 16:47:15,484 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: produce error com.bhr.infra.messaging.exception.PMException: JMSException at com.bhr.infra.messaging.PMHandler.send(PMHandler.java:419) at com.bhr.epc.infra.messaging.util.MessagingUtilServlet.produce(MessagingUtilServlet.java:312) at com.bhr.epc.infra.messaging.util.MessagingUtilServlet.service(MessagingUtilServlet.java:74) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1072) at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465) at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6981) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121) at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3892) at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2766) at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183) Caused by: javax.jms.JMSException: MQJMS2007: failed to send message to MQ queue at com.ibm.mq.jms.services.ConfigEnvironment.newException(ConfigEnvironment.java:553) at com.ibm.mq.jms.MQMessageProducer.sendInternal(MQMessageProducer.java:1589) at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:1012) at com.ibm.mq.jms.MQMessageProducer.send(MQMessageProducer.java:1046) at com.bhr.infra.messaging.PMQueueSender.send(PMQueueSender.java:57) at com.bhr.infra.messaging.PMHandler.send(PMHandler.java:410) ... 13 more 13 Oct 2006 16:47:15,486 ERROR MessagingUtilServlet [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'][]: **********EXCEPTION TRACE END**************åŽŸå› åˆ†æžå’Œè§£å†Ïx–¹æ³?
It may be caused by use of old version MQ jar. It can receive message, but cannot send message.
˜q™ä¸ªé—®é¢˜çš„æ ¹æœ¬åŽŸå› ç”±äºŽå“应本‹Æ¡è¯·æ±‚çš„Responseå¯¹è±¡çš„çŠ¶æ€æ˜¯å·²æäº¤çжæ€é€ æˆçš? 它ä¸å…许å“应æäº¤å¤šæ¬¡ã€? 什么时候Response对象的状æ€å˜æˆå·²æäº¤çжæ€ï¼šå½“ä½ çš„åº”ç”¨å·²¾l实çŽîCº†™åµé¢è·Œ™{逻辑ã€? é€šå¸¸åŽŸå› åQ? 1åQ?å¦‚æžœä½ ä‹É用了communityçš„è¯åQ?community的安全认è¯å’ŒæŽˆæƒå¦‚果没有通过åQŒcommunity内部会进行页é¢èŸ©è½¬ã€‚ä½†ä½ çš„åº”ç”¨(对于workshop应用的è¯åQŒæŒ‡çš„æ˜¯action)åˆè¯•图进行页é¢èŸ©è½¬ï¼Œž®×ƒ¼šå‡ºçް˜q™æ ·çš„问题ã€? /** * @jpf:action * @jpf:forward name="page" path="page.jsp" */ protected Forward actionMethod() { //å¦‚æžœå·²ç»æäº¤äº†å“åº”ï¼Œä½ ä»ç„¶è¯•囑ֆ‹Æ¡è¿›è¡Œé¡µé¢èŸ©è½¬ï¼Œå›_†‹Æ¡æäº¤å“应,å¯èƒ½å‡ºçŽ°é—®é¢˜ //通常å¯ä»¥åŠ ä¸€ä¸ªåˆ¤æ–? if (!getResponse().isCommitted()) { return new Forward("success"); } else { return null; } } protected void beforeAction() { SecurityManager.checkAuthorization(getRequest(), getResponse(), config.getString( CDConstants.CREATE_TERM_ACTION_NAME, "")); //˜q™ä¸ªè°ƒç”¨å¯èƒ½å®žçŽ°äº†é¡µé¢èŸ©è½¬ï¼ŒåÏx交å“åº? } 注æ„JSPä¸å®žçް页é¢èŸ©è½¬åŽåQŒåŠ return è¯å¥é˜²æ¢¾l§ç®‹æäº¤å“应: <% SecurityManager.checkAuthorization(getRequest(), getResponse(), config.getString( CDConstants.CREATE_TERM_ACTION_NAME, "")); { //å¯èƒ½æœ‰å®žçް页é¢èŸ©è½¬é€»è¾‘ ……………forward(); return;//è®°å¾—åŠ retrun. } %> 2. .如果没有使用communityçš„è¯åQŒä¸‹é¢æƒ…景也会出现这个问é¢? /** * @jpf:action * @jpf:forward name="page" path="page.jsp" */ protected Forward actionMethod() //直接æ“作Response对象写å“åº? getResponse().getPrintWriter().println(); … / // åˆæ‰§è¡Œçš„™åµé¢è·Œ™{åQŒä¹Ÿå¯èƒ½å‡ºçŽ°é—®é¢˜ return new Forward("index"); }
Error message like below in Web Page is displayed: Page Flow: /com/xxxx/xxx/xxx.jpf Action: update Page Flow Error - No Relevant Page You have tried to return to a recent page in the current page flow through return-to="currentPage", but there is no appropriate page. Exception's stack trace: Exception: No previous page for return-to="currentPage" on action create in page flow /com/gems/mt/web/CreateReleaseCntr/CreateReleaseCntrController.jpf. com.bea.wlw.netui.pageflow.NoPreviousPageException: No relevant page for return-to="currentPage" on action create in page flow /com/gems/mt/web/CreateReleaseCntr/CreateReleaseCntrController.jpf. at com.bea.wlw.netui.pageflow.FlowController.doReturnToPage(FlowController.java:1328) at com.bea.wlw.netui.pageflow.FlowController.forwardTo(FlowController.java:1023) at com.bea.wlw.netui.pageflow.PageFlowController.forwardTo(PageFlowController.java:606) at com.bea.wlw.netui.pageflow.FlowController.internalExecute(FlowController.java:765) ...åŽŸå› åˆ†æžå’Œè§£å†Ïx–¹æ³?
When a new page flow is created and its current page is null (it mean you visit at the fist time), so such an exception like NoPreviousPageException occur if you use return-to="currentPage". if a new page flow finish a successful forward, it will treat last page as current page so that we can use current page to display error message conveniently. Solution: ensure page flow finish a successful forward and use current page again. You can also use path="specificPage.jsp" instead of return-to="currentPage" if your original return-to is just one specific page.
Recently found, there is a memory leak bug for list cell renderer in both JDK 1.4.x and JDK 5 (don’t know whether has the same bug in earlier JDK). The component returned from getListCellRendererComponent() method could not be GC, and all its referenced objects also could not be GC. Unfortunately, this bug is only fixed in JDK 6.
So currently, if a JList use the ListCellRenderer, but only holds a little resource (eg: the JList only has little items, and the component is returned from ListCellRenderer is a simple JLable), you may not care about the memory leak.
But if a JList use the ListCellRenderer, and holds a large resource, you should remember to use the following way to avoid memory leak.
Work Around: Subclass JList and invoke removeAll after painting is done:
      public class xxxList extends JList {
           private CellRendererPane renderer;
           private CellRendererPane getRenderer() {
               if (renderer == null) {
                   for (int i=0; i<getComponents().length; i++) {
                                         Component c = getComponents()[i];
                       if (c instanceof CellRendererPane) {
                           renderer = (CellRendererPane)c;
                           break;
                       }
                   }
               }
               return renderer;
           }
           protected void paintComponent(Graphics g) {
               super.paintComponent(g);
               CellRendererPane renderer = getRenderer();
               if (renderer != null) {
                   renderer.removeAll();
               }
           }
       }
Please note that in the state classes, if a method is supported by stateA and not supported by stateB.Â
Then, in stateB, the method body will throw an exception (IllegalArgumentException) to indicate that coder call the wrong method in the wrong state.
Example, in VesselPlanView.java, public boolean addStowage(...). This method is only meaningful to stowageView.
public boolean addStowage(IlvManager manager, List transformList, IlvGraphic stowage, String stadBayN,
                             boolean isSelect) {
       throw new IllegalArgumentException(
               "GrVessel::addStowage-->be sure the vessel at stowage view!");
   }
Hence, in PlanView, the method body will throw exception.
Just to share with you a better way to code.