Release 1.0?
I know that open source developers normaly don't commit to deadlines, but I like to know if release 1.0 of struts is near. We are currentlyat the beginning of a new project and I like to use Struts. But I'm not very found of using nightly builds. On the other hand the nightly builds already have some problems fixed that we now have to work around in 0.5. So if anyone could give me an idea of when 1.0 is due, it then mightbe easier for me to make a decision. Thanx in advance, Allan Schweitz
Generic design for Business Logic Beanies (long)
Hi struts users ! As announced here comes a more detailed outline of how I think one could have a generalized data interface. The code provided should be enough to get the general idea. Generic Entity class package foo.bar.datamodel; public class MyEntity implements java.io.serializable { private type1 __data1; public type_1 getData_1() {return __data1;} public void setData_1(type_1 v) {__data1 = v;} private type2 __data2; public type_2 getData_2() {return __data2;} public void setData_2(type_2 v) {__data2 = v;} ... (etc.) } Generic interfaces for generic Retriever classes package foo.bar.base; public interface RetrieveSingle { public java.io.serializable select(java.sql.Connection connection); public java.io.serializable select(java.sql.Connection connection, SqlQuery sqlQuery); } --- package foo.bar.base; public interface RetrieveMany { public java.util.List selectMany(java.sql.Connection connection); public java.util.List selectMany(java.sql.Connection connection, SqlQuery sqlQuery); } Generic connection helper class === package foo.bar.base; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.naming.Context; public class MyConnection { private DataSource __dataSource = null; private InitialContext __initialContext = null; private Connection __connection = null; //have to check if synchronized is necessary synchronized private Context getInitialContext() throws NamingException { if (null==__initialContext) { __initialContext = new InitialContext(); } return __initialContext; } public Connection getConnection(String szPool) { if (__connection == null) { if (__dataSource == null) { try { __dataSource = (DataSource) getInitialContext().lookup(null==szPool?"foo.bar.genericpool":szPool); } catch(NamingException e) { // add more errorlogging e.printStackTrace(); } } try { __connection = __dataSource.getConnection(); } catch(SQLException e) { // add more errorlogging e.printStackTrace(); } } return __connection; } public void closeConnection() { if (__connection != null) { try { __connection.close(); __connection = null; } catch(SQLException e) { // add more errorlogging e.printStackTrace(); } } } } Generic Retriever class === package foo.bar.datamodel; public class MyRetriever implements RetrieveSingle, RetrieveMany { private final static String __szSqlStmt = some SQL query // e.g. "SELECT a.field1 as field_1, a.field2 as field_2 ... a.fieldn as field_n FROM table1 a"; public MyEntity select(java.sql.Connection connection) { return select(connection, null); } public IfinEntity select(java.sql.Connection connection, SqlQuery sqlQuery) { MyEntity result = new MyEntity(); String szQuery; if (sqlQuery != null) { SqlQueryBuilder sqlBuilder = new SqlQueryBuilder(); szQuery = sqlBuilder.buildSqlString(__szSqlStmt, sqlQuery); } else { szQuery = __szSqlStmt; } Statement stmt = null; ResultSet resultSet = null; try { stmt = connection.createStatement(); resultSet = stmt.executeQuery(szQuery); if (resultSet.next()) { result.setData_1(resultSet.gettype_1("field_1")); result.setData_2(resultSet.gettype_2("field_2")); ... result.setData_n(resultSet.gettype_n("field_n")); } resultSet.close(); stmt.close(); } catch(SQLException e) { // add more errorlogging e.printStackTrace(); return null; } return result; } public java.util.List selectMany(java.sql.Connection connection) { return selectMany(connection, null); } public java.util.List selectMany(java.sql.Connection connection, SqlQuery sqlQuery) { java.util.ArrayList result = new java.util.ArrayList(); String szQuery; if (sqlQuery != null) { SqlQueryBuilder sqlBuilder = new SqlQueryBuilder();
Re: Business Logic Beanies
Being able to autogenerate the "logical data beans" would be excellent! And very much in keeping with the rest of the Struts framework. Ideally, this would be a mechanism that could also be used in other applications (e.g. Swing-based). So, in general terms, it seems we're coming down to this: (data bean) :: (query bean) :: (action form) :: (action object) | JSP Where the DataBean is totally unaware of Struts, and the QueryBean might be only vaguely aware, through use of the GenericConnection and GenericDataSource classes. Sounds good. In my ignorance (and still being somewhat new to struts) I wasn't aware of the aforementioned generic classes. Of course the generic outline I just posted in another mail should be adjusted to use these. I would also say that the QueryBean should be able to read its base query from a resource file, so that these can be adjusted without recompiling (and centralized for control and documentation). Agreed. Talking about this I think struts also needs some kind of application configuration file. AFAICT the resources won't suffice as I might need configuration information inside my EJB etc. as well. Or is there something already which simply escaped me ? Best, Michael
Re: Release 1.0?
The difference between the current nightly builds of 12/30 and a 0.9 release is really semantic; at this point,the nightly builds really amount to 0.9.40, 0.9.41, 0.9.42, releases. I believe that we are in feature lock for 1.0, and the bottleneckismostly packaging and documentation. Craig's asked me to help with that, but I will be tied up for the rest of this week at least (putting the current version of Struts to work). My experience with Stuts is that it is solid and reliable, and that nightly builds are not problematic. Personally, I would recommend picking a nightly build (say 12/30), and coming current. The release notes easilybridge the gap in the User Guide between 0.5 and 1.0, and the rest of the documentationseems current. (And of course nothing beats Craig's well-documented code!)The version numbers have more to do with management politics than actual development. *** REPLY SEPARATOR ***On 1/3/2001 at 9:32 AM Allan Schweitz wrote: I know that open source developers normaly don't commit to deadlines, but I like to know if release 1.0 of struts is near. We are currentlyat the beginning of a new project and I like to use Struts. But I'm not very found of using nightly builds. On the other hand the nightly builds already have some problems fixed that we now have to work around in 0.5. So if anyone could give me an idea of when 1.0 is due, it then mightbe easier for me to make a decision. Thanx in advance, Allan Schweitz
Re: Pre-compiled JSPs in action.xml path=URI possible ??
Ron Bolin wrote: Is struts designed to work with pre-compiled JSPs? Is it possible in struts 1.0 to define and use classes in the forward path argument rather than JSP as shown below. I am interested in speeding up the initial screens in our project. I have been toying with this, bus so far have not been able to get it to work. Any insight would be appreciated. The example below does not reflect the new Struts 1.0 ActionMappings, but is being presented for clarification. Example using JSP not pre-compiled. !-- Main Administration-- actionpath="/mainAdmin" actionClass="org.hp.awsadmin.action.MainAdminAction" formAttribute="mainForm" formClass="org.hp.awsadmin.form.MainForm" forward name="success" path="/jsp/awsMain.jsp"/ /action Example using compiled JSP class. !-- Main Administration-- actionpath="/mainAdmin" actionClass="org.hp.awsadmin.action.MainAdminAction" formAttribute="mainForm" formClass="org.hp.awsadmin.form.MainForm" forward name="success" path="/classes/awsMain"/ /action Thanks in advance. There is nothing about Struts that would care about precompiled versus not precompiled JSP pages, but the details of how you set them up depends on the servlet container you are using. With Tomcat, for example, running the "jspc" command line tool will compile all your pages, but it will also create a bunch of servlet and servlet-mapping tags that need to go into your web.xml file. In particular (at least for Tomcat), though, the path of a JSP page does *not* change when you use precompiled pages. The reason this works is that the compiler generates a servlet mapping for "/jsp/awsMain.jsp" for you -- and, because this is an exact match, it has higher priority than extension mapping on "*.jsp", which would send the page back to the JSP servlet. Try leaving the path for the compiled case the same as the path for the uncompiled case, and make sure that you've included the necessary stuff in web.xml. Ron Craig McClanahan
Re: Business Logic Beanies
Ted Husted wrote: Being able to autogenerate the "logical data beans" would be excellent! And very much in keeping with the rest of the Struts framework. Ideally, this would be a mechanism that could also be used in other applications (e.g. Swing-based). So, in general terms, it seems we're coming down to this: (data bean) :: (query bean) :: (action form) :: (action object) | JSP Where the DataBean is totally unaware of Struts, and the QueryBean might be only vaguely aware, through use of the GenericConnection and GenericDataSource classes. You should program in terms of the javax.sql.DataSource interface, rather than hard coding GenericDataSource. That way, you will not be tying yourself to the Struts connection pool implementation. By the same reasoning, the thing you get back from DataSource.getCoinnection() is just a java.sql.Connection -- you do *not* want to be dependent on any particular underlying implementation. I would also say that the QueryBean should be able to read its base query from a resource file, so that these can be adjusted without recompiling (and centralized for control and documentation). If you do it this way, do you need more than one QueryBean? Couldn't you create a generic one that processes different kinds of query strings based on the name of the resource you told it to read? In my own work, I subclassed the QueryBean from ActionFormBean (in case I figure out how to read it from the struts-config file). Let's say your QueryFormBean has a property named "resource", with corresponding getResource() and setResource() methods. This should be configured by doing something like this in struts-config.xml: form-bean name="SearchForm" type="com.mycompany.mypackage.SearchFormBean" set-property property="resource" value="...path to resource..."/ /form-bean but it won't work until tonight's nightly build, when I make it legal to embed set-property/ inside a form-bean :-) In the meantime, I tried to give it a standard properties file to read the base SQL strings. No problem if I hardcode a system path, but no go if I try to find it on the classpath. To wit: public void resetQuery() throws IOException { // Must call setName first! Properties props = new Properties(); String name = "d:\\QueryFormBean.properties"; /* InputStream is = null; is = this.getClass().getClassLoader().getResourceAsStream(name); if (is != null) { props.load(is); is.close(); setQuery(props.getProperty(getName())); } */ FileInputStream in = new FileInputStream(name); props.load(in); setQuery(props.getProperty(getName())); in.close(); } The commented code was taken from the Struts PropertyMessageResource, but doesn't seem to work. (Not that I understand what it's doing - I'm just banging the rocks together!) If I hardcode the path, everything is hunky-dory. If you want to use ClassLoader().getResourceAsStream(name), the name you pass should look like a Java class name, but with periods changed to slashes. In other words, if your class is in package com.mycompany.mypackage, and your resource file name is "QueryFormBean.properties", the resource name is: com/mycompany/mypackage/QueryFormBean.properties This resource will be looked up along the runtime classpath for your web app, just like classes are looked up. A hacked example of all this, that works around the properties glitch, is available as a ZIP file at http://husted.com/about/struts as "Struts with a Fruit Glaze". Comments appreciated! -- Ted Husted, Husted dot Com, Fairport NY USA. -- Custom Software ~ Technical Services. -- Tel 716 425-0252; Fax 716 223-2506. -- http://www.husted.com/ Craig
Re:Struts Tutorial on http://www.informIT.com ?
Looking through the archives, I read there is a struts tutorial on http://www.informIT.com ?? I looked and couldn't find it. does anyone know if it's still there, who the author would be (searches for struts, apache, tag library, etc yielded zippo) I just found it! Browsing by topic, choose Internet/Java and u'll find "Featured Expert Maneesh Sahu" []'s Jorge Kazuo [EMAIL PROTECTED] ICQ #591189
Re: Business Logic Beanies
"Craig R. McClanahan" wrote: form-bean name="SearchForm" type="com.mycompany.mypackage.SearchFormBean" set-property property="resource" value="...path to resource..."/ /form-bean Oops, this really needs to include a reference to the custom ActionFormBean subclass to use. You can do this (again, as of tonight's nightly build) in one of two ways: * Set an initialization parameter named "formBean" on the controller servlet that names the class to be used for all form-bean elements. * On each individual formBean, include a "className" attribute that identifies the ActionFormBean subclass to use for this particular entry (so you can have different ones). Craig
Re: Configuring Struts for Tomcat + Apache
James Howe wrote: Can anyone offer some tips (or samples) of ways to configure Struts in a Tomcat + Apache environment? I want to be able to serve static content from my web application from Apache but servlet code obviously needs to go to Tomcat. Getting Tomcat to work with a new web application seems as easy as putting a .war file in the webapps directory, but it seems that more work is involved in getting Apache to do its part. For example, if I access my web app directly from Tomcat with a URL like this: http://localhost:8080/myapp I get the index.jsp page which is defined as my welcome page. However, if I use the URL http://localhost/myapp I get the directory of files in my web application. If anyone can offer tips on how best to configure my Apache+Tomcat environment to support Struts applications, I would appreciate it. There are two things you have to configure in httpd.conf to make this work: * Tell Apache that JSP pages can be used as welcome pages: DirectoryIndex index.html index.jsp * Tell Apache to forward "*.do" URIs to Tomcat so that Struts can process them (assumes you are using MOD_JSERV): AddHandler jserv-servlet .do (There is an analogous setting for MOD_JK, but I do not remember it off the top of my head). Thanks. Craig
New Struts Tutorial, Request for Writings Section
Located here: http://gallery.bluestone.com/scripts/SaISAPI.dll/Gallery.class/demos/trailMa ps/index.jsp (if the link breaks mid-line in this email, just go to http://gallery.bluestone.com, then go to "demos" then to "Trail Maps") There is a new trail-map style tutorial on Struts compliments of Bluestone Software. It's based on one of the more recent builds of Struts, so it should be a good start for people just learning Struts with the 1.0 release so close. It'd be nice to have a more detailed "External Documentation" or "Links" section on the Struts website linking to all the tutorials and writings available for struts, to make learning Struts faster and easier. I'd like to put together this section, then hopefully just hand it off to Craig and he could post it to the site. If anyone has links to tutorials and writings on Struts, please let me know so that I can add them to this section. I'm looking for demos, articles, tutorials, and documented user experiences. Thanks, Mike Schachter
Re: New Struts Tutorial, Request for Writings Section
On 1/3/2001 at 3:04 PM Schachter, Michael wrote: I'd like to put together this section, then hopefully just hand it off to Craig and he could post it to the site. If anyone has links to tutorials and writings on Struts, please let me know so that I can add them to this section. I'm looking for demos, articles, tutorials, and documented user experiences. See http://husted.com/about/struts - take whatever you can use! The trials look great! I'll look forward to reading them this weekend! -- Ted Husted, Husted dot Com, Fairport NY USA. -- Custom Software ~ Technical Services. -- Tel 716 425-0252; Fax 716 223-2506. -- http://www.husted.com/
Re: Configuring Struts for Tomcat + Apache
James Howe wrote: At 11:43 AM 1/3/2001 -0800, you wrote: James Howe wrote: Can anyone offer some tips (or samples) of ways to configure Struts in a Tomcat + Apache environment? [...] There are two things you have to configure in httpd.conf to make this work: * Tell Apache that JSP pages can be used as welcome pages: DirectoryIndex index.html index.jsp * Tell Apache to forward "*.do" URIs to Tomcat so that Struts can process them (assumes you are using MOD_JSERV): AddHandler jserv-servlet .do That helps quite a bit but I have one additional question. When running straight Tomcat, I can deploy a new web application by simply putting the WAR file in the webapps directory. I can then access the application thusly: http://localhost:8080/fooapp (assumes fooapp exists in the webapps directory). However, it seems as if I need to modify the tomcat.conf file referenced by apache to define an alias for my application something along the lines of: Alias /fooapp C:\Web\tomcat\webapps\fooapp Directory "C:\Web\tomcat\webapps\fooapp" Options Indexes FollowSymLinks /Directory Location /fooapp/WEB-INF/ AllowOverride None deny from all /Location LocationMatch /fooapp/*.jsp SetHandler jserv-servlet /LocationMatch LocationMatch /fooapp/*.do SetHandler jserv-servlet /LocationMatch If I want my user to enter something like http://localhost/fooapp and have Apache serve static stuff and Tomcat serve servlet stuff, do I need to update my tomcat.conf file everytime I add a new web application to the webapps directory? For Tomcat 3.x you do have to do this. The web connector currently being built for Tomcat 4.0 does not -- it will require only a single "mount" type command per webapp. Thanks again. James W. Howe mailto:[EMAIL PROTECTED] Allen Creek Software, Inc. pgpkey: http://ic.net/~jwh/pgpkey.html Ann Arbor, MI 48103 Craig
Re: Business Logic Beanies
On 1/3/2001 at 11:06 AM Craig R. McClanahan wrote: If you do it this way, do you need more than one QueryBean? Couldn't you create a generic one that processes different kinds of query strings based on the name of the resource you told it to read? Now that you mention, it could be used a generic bean now; I've been using the name property as the key into the resource, which is meant to store all the queries used anywhere by the application. So that part is probably working already. I was subclassing it to provide a way to hand Struts a collection (based on the ResultSet) for the tags to play with. When we upgrade the tags for rowsets, I might be able to skip this step and use the rowset where I'm generate a collection now. Today, I'm just using the subclass to do something like public FruitSalesDetail[] fetchDetail(int from, int count) throws SQLException { // TODO - Generate exception if from 1 setFrom(from); // optimistic result setCountResult(count); // calculate where Prev would have been; but don't go negative if (fromcount) {setPrev(from-count);} else {setPrev(1);} FruitSalesDetail[] detail = new FruitSalesDetail[count]; // resultSet.absolute(from); // FIXME if 1 starts at 2 ? for (int i = 1; i from; i++) { result.next(); } for (int i = 0; i count; i++) { if (result.next()) { detail[i] = new FruitSalesDetail(); detail[i].setYear(result.getInt(1)); detail[i].setQuarter(result.getInt(2)); detail[i].setApples(result.getInt(3)); detail[i].setApplesales (result.getFloat(4)); detail[i].setOranges(result.getInt(5)); detail[i].setOrangesales (result.getFloat(6)); detail[i].setTopseller(result.getString(7)); from++; } else { setCountResult(i); break; } } if (result.next()) {setNext(from);} else {setNext(1);} return(detail); } The "detail" it returns gets inserted directly into the page context page.setAttribute("fruitSalesDetail",salesQuery.fetchDetail()); where iterate can snag it with logic:iterate id="row" name="fruitSalesDetail" length="length" scope="page" The next/prev stuff lets me call the JSP again for the next block of records, or rollback with if (action.equals("prev")) { sQuery.setNext(sQuery.getPrev()); } // where sQuery is a QueryBean property of my ActionForm. The 30,000 foot view is ActionForm - ActionDataForm - FruitSalesForm // Provides JDBC and PageContext hooks ActionFormBean - QueryFormBean - FruitSalesQuery // Implements JDBC calls; Maintains query state between requests. Action - FruitSalesAction // Resets FruitSalesQuery bean to start new round of requests. FruitSalesDetail // Generic bean to encapsulate fields returned by query // Inserted as an array into page context by FruitSalesForm Of course, suggestions for an alternate model would be appreciated! The endgame is just to provide something the iterate and option tags can use. A working example is available at http://husted.com/about/struts -- Ted Husted, Husted dot Com, Fairport NY USA. -- Custom Software ~ Technical Services. -- Tel 716 425-0252; Fax 716 223-2506. -- http://www.husted.com/
Re: I want the reques t URL.
Johan Compagner wrote: by the way when i want default object(s) be initalized for every session object that is created. What is the best way for doing that? Something like the Locale object problem (not initialized when you don't use the form:html tag. I want a Customer object for every session object i make, without checking this one every page i created (when users bookmark it) In a servlet 2.3 environment (like Tomcat 4.0), you would be able to do this by using the new "application event listener" feature. One of the listeners you can define hears about all new session creations (no matter where they came from), so you could use it to populate your default objects. In a 2.2 environment, however, I can't think of a solution any better than what we did with locales - put logic in both the controller servlet *and* a tag that is used on every page. If you decide to go the latter route, one thing you might think about is subclassing an existing tag class (like the form:html tag) that is usually used on every page anyway, and have it do the extra work for you. johan Craig
RE: Problem with Digester used standalone (REF: BugRat report #692)
NullPointerException using CallMethodRule in Digester. This occurs if the parameters to the method call are specified as being primitive types. For example, the following excerpt from the Digester init: digester.addCallMethod( "quickmenu-config/entry/visibility", //"setAppIDSense", 1, new String[] {"java.lang.Boolean"}); "setAppIDSense", 1, new String[] {"boolean"}); digester.addCallParam( "quickmenu-config/entry/visibility", 0, "sense"); In this case, configuring the CallMethodRule to invoke a method with a primitive data type as a parameter fails. The commented out version using the Boolean wrapper object succeeds. (NOTE: The destination object has the method with both signatures). Stack trace from my code: = End event threw exception java.lang.NullPointerException: at org.apache.struts.util.BeanUtils.convert(BeanUtils.java:131) at org.apache.struts.digester.CallMethodRule.end(CallMethodRule.java:226) at org.apache.struts.digester.Digester.endElement(Digester.java:373) at com.sun.xml.parser.Parser.maybeElement(Parser.java:1413) at com.sun.xml.parser.Parser.content(Parser.java:1499) at com.sun.xml.parser.Parser.maybeElement(Parser.java:1400) at com.sun.xml.parser.Parser.content(Parser.java:1499) at com.sun.xml.parser.Parser.maybeElement(Parser.java:1400) at com.sun.xml.parser.Parser.parseInternal(Parser.java:492) at com.sun.xml.parser.Parser.parse(Parser.java:284) at javax.xml.parsers.SAXParser.parse(SAXParser.java:155) at javax.xml.parsers.SAXParser.parse(SAXParser.java:77) at org.apache.struts.digester.Digester.parse(Digester.java:708) at loadQuickmenu.readConfig(loadQuickmenu.java:32) at loadQuickmenu.main(loadQuickmenu.java:41) To correct this issue in struts, add new method to BeanUtils.java [Class forName(String classname)] which defers to/mirrors the version in Class but also handles primitive data types. Modify constructor in org/apache/struts/digester/CallMethodRule.java to call BeanUtils.forName(String) rather than Class.forName(String) to convert the className to a Class Object. The updated files are attached. e -- ___ Elod Horvath ('e') / ITFAIS Records (http://www.itfais.com/) /* * $Header: /home/cvspublic/jakarta-struts/src/share/org/apache/struts/util/BeanUtils.java,v 1.18 2000/12/31 04:26:37 craigmcc Exp $ * $Revision: 1.18 $ * $Date: 2000/12/31 04:26:37 $ * * * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright *notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright *notice, this list of conditions and the following disclaimer in *the documentation and/or other materials provided with the *distribution. * * 3. The end-user documentation included with the redistribution, if *any, must include the following acknowlegement: * "This product includes software developed by the *Apache Software Foundation (http://www.apache.org/)." *Alternately, this acknowlegement may appear in the software itself, *if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software *Foundation" must not be used to endorse or promote products derived *from this software without prior written permission. For written *permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" *nor may "Apache" appear in their names without prior written *permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. *
Unsuscribe
Unsuscribe