{"id":362,"date":"2006-07-24T12:05:43","date_gmt":"2006-07-24T18:05:43","guid":{"rendered":"http:\/\/www.mooreds.com\/wordpress\/?p=362"},"modified":"2006-08-10T23:41:48","modified_gmt":"2006-08-11T05:41:48","slug":"calendartag-a-simple-jsp-calendar-component","status":"publish","type":"post","link":"https:\/\/www.mooreds.com\/wordpress\/archives\/362","title":{"rendered":"CalendarTag: A simple JSP Calendar Component"},"content":{"rendered":"<p><em>Update, 8\/10\/2006: There&#8217;s at least <a href=\"http:\/\/www.aoc.nrao.edu\/%7Ebwaters\/pub\/taglib\/calendar-taglib.html\">one other open source calendar generation taglib<\/a> that looks like it&#8217;s worth a download (even though it&#8217;s older).  That author hoped that code would make it into <a href=\"http:\/\/jakarta.apache.org\/taglibs\/\">the Jakarta Taglibs<\/a> but I didn&#8217;t find any evidence of that.<\/em><\/p>\n<p>I was looking around at jsp calendar components for a client.  I&#8217;d previously <a href=\"http:\/\/www.mooreds.com\/weblog\/archives\/000271.html\">had a hard time<\/a> finding a decent one, so I didn&#8217;t hold out much hope.  Luckily, this search was slightly different&#8211;I don&#8217;t need any fancy features, just a simple calendar display rendered in html, with  links on the day numbers.  In addition, the calendar needs to be indexable, so <a href=\"http:\/\/calendarxp.net\/\">FlatCalendarXP<\/a>, which I&#8217;ve used before, is not an option.<\/p>\n<p>I looked at the <a href=\"http:\/\/www.servletsuite.com\/servlets\/htmlcal.htm\">HtmlCalendarBean<\/a> and the <a href=\"http:\/\/www.servletsuite.com\/servlets\/caltag.htm\">Calendar Taglib<\/a>, both from <a href=\"http:\/\/www.servletsuite.com\/\">ServletSuite<\/a>.  I expected the price to be reasonable, but didn&#8217;t expect source, which was important for the client.<\/p>\n<p>A bit of digging around on <a href=\"http:\/\/www.sourceforge.net\/\">SourceForge<\/a> found the perfect project: <a href=\"http:\/\/calendartag.sourceforge.net\/\">CalendarTag<\/a>.  This project looks abandoned, but the author got things into good shape before ceasing development.  I&#8217;d say the project is mature, rather than abandoned.  In addition, he responded to my questions (including &#8220;is this project alive?&#8221;) in less than 24 hours.<\/p>\n<p>I found the documentation to be very useful.  In addition, you can customize the<br \/>\ncalendar&#8217;s output to a very large degree.  I especially like the decorator, which lets you control exactly how each day is displayed by implementing <a href=\"http:\/\/calendartag.sourceforge.net\/apidocs\/org\/calendartag\/decorator\/CalendarDecorator.html\">a relatively simple interface<\/a> or extending a <a href=\"http:\/\/calendartag.sourceforge.net\/apidocs\/org\/calendartag\/decorator\/DefaultCalendarDecorator.html\">a class<\/a>.<\/p>\n<p>Make no mistake.  This is a simple component which just displays a calendar in html.  There&#8217;s no support for users or events (<em>Update 3:24.  I should have read the docs more closely and said, there&#8217;s no built in support for events or users.  From within the calendar, you have access to the request and so can code up <a href=\"http:\/\/calendartag.sourceforge.net\/tutorial.html#Creating_a_calendar_with_content__events_\">event handling<\/a> and\/or user specific calendars.<\/em>).  If you want those features, I&#8217;d look at a more complex calendaring system.  Calendartag does something simple and does it well.<\/p>\n<p>One tip&#8211;you&#8217;ll need to have the <code>standard-1.0.4.jar<\/code> file available to your web application, as well as the <code>calendartag-1.0-rc4.jar<\/code> file, otherwise you see this rather fearsome exception:<\/p>\n<div><code> <\/code><\/p>\n<pre>org.apache.jasper.JasperException: org\/apache\/taglibs\/standard\/tag\/el\/core\/ExpressionUtil\r\nat org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:254)\r\nat org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)\r\nat org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)\r\nat javax.servlet.http.HttpServlet.service(HttpServlet.java:853)\r\nat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)\r\nat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)\r\nat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2422)\r\nat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)\r\nat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:163)\r\nat org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:199)\r\nat org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828)\r\nat\r\norg.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:700)\r\nat org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:584)\r\nat org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)\r\nat java.lang.Thread.run(Thread.java:595)\r\n\r\nroot cause\r\n\r\njavax.servlet.ServletException: org\/apache\/taglibs\/standard\/tag\/el\/core\/ExpressionUtil\r\nat org.apache.jasper.runtime.PageContextImpl.handlePageException(PageContextImpl.java:536)\r\nat org.apache.jsp.index_jsp._jspService(index_jsp.java:59)\r\nat org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:137)\r\nat javax.servlet.http.HttpServlet.service(HttpServlet.java:853)\r\nat org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:210)\r\nat org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)\r\nat org.apache.jasper.servlet.JspServlet.service(JspServlet.java:241)\r\nat javax.servlet.http.HttpServlet.service(HttpServlet.java:853)\r\nat org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247)\r\nat org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193)\r\nat org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)\r\nat org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2422)\r\nat org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180)\r\nat org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171)\r\nat org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)\r\nat org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:163)\r\nat org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174)\r\nat\r\norg.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643)\r\nat org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480)\r\nat org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995)\r\nat org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:199)\r\nat org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828)\r\nat org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:700)\r\nat org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:584)\r\nat org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)\r\nat java.lang.Thread.run(Thread.java:595)<\/pre>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Update, 8\/10\/2006: There&#8217;s at least one other open source calendar generation taglib that looks like it&#8217;s worth a download (even though it&#8217;s older). That author hoped that code would make [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-362","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/comments?post=362"}],"version-history":[{"count":0,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/posts\/362\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/media?parent=362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/categories?post=362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mooreds.com\/wordpress\/wp-json\/wp\/v2\/tags?post=362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}