Changes between Version 1 and Version 2 of JavaMapscriptUsing


Ignore:
Timestamp:
Jul 17, 2009, 1:10:03 AM (11 years ago)
Author:
unicoletti
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • JavaMapscriptUsing

    v1 v2  
    1 draft
     1{{{
     2#!html
     3<a name="N1000C"></a><a name="My+Notes"></a>
     4<h3>My Notes</h3>
     5<div>
     6<p>
     7        Many people ask questions about Java Mapscript on <em>mapserver-users</em>. This is an attempt
     8        to record my answers to them, my impressions on mapserver and Java Mapscript.
     9        Before you proceed I must warn you that the following are my opinions and
     10        they might not be endorsed or approved by the mapserver community at all.
     11        </p>
     12<p>
     13        Most of this is <strong>LINUX</strong> specific, but some is general.
     14        </p>
     15</div>
     16               
     17<a name="N1001F"></a><a name="Building+Java+Mapscript"></a>
     18<h3>Building Java Mapscript</h3>
     19<div>
     20<p>
     21                Guidelines for building a working Java Mapscript.
     22                </p>
     23<a name="N10028"></a><a name="The+Golden+Rule:+KISS!+(Keep+it+simple,+stup^H^H^H^sir!)"></a>
     24<h4>The Golden Rule: KISS! (Keep it simple, stup^H^H^H^sir!)</h4>
     25<div>
     26<p>
     27                                Mapserver is really a big piece of software with plenty of functionalities (some say it is the most advanced web
     28                                mapping software) and chances are you do need all of them. If you are a newbie to mapserver
     29                                or to Java mapscript try to understand what you need and stick with it, removing the unneeded features.
     30                                <br />
     31                                This approach is generally suggested because:
     32                                </p>
     33<ul>
     34                                       
     35<li>it reduces the number of lines of code involved and thus reduces the number of possible
     36                                        bugs that could bite</li>
     37                                       
     38<li>it makes for a smaller binary which is more efficient</li>
     39                                       
     40<li>in case of a crash the number of suspects is lower and will speed up investigation
     41                                        and in some cases resolution</li>
     42                                       
     43<li>it requires less software to be installed on your computer which makes it easier to
     44                                        mantain in the long term</li>
     45                                       
     46<li>the first three items apply (with recursion) to the previous</li>
     47                                       
     48<li>if you ask for help on the mailing list the first general advice is to remove components you
     49                                        don't use: so do it in advance</li>
     50                               
     51</ul>
     52<p>
     53                                See <a href="#compile">below</a> for a example of a basic (but working) mapserver/mapscript build example.
     54                                </p>
     55</div>
     56<a name="N10050"></a><a name="How+do+I+disable+option+X?"></a>
     57<h4>How do I disable option X?</h4>
     58<div>
     59<p>
     60                                Chances are that even if you do not need tiff or mysql support it will get built in anyway
     61                                because the configure script detects their libraries. In all cases you should review
     62                                the output of the configure script and then use the proper command line argument to disable unwanted
     63                                features.
     64                                </p>
     65<p>
     66                        When running the <em>./configure</em> program use the
     67                        <em>--disable-X</em> option. You can get the list of available options by running:
     68                        </p>
     69<pre class="code">./configure --help<br />                      </pre>
     70</div>
     71<a name="N10068"></a><a name="Know+your+enemy"></a>
     72<h4>Know your enemy</h4>
     73<div>
     74<p>
     75                                Certain libraries/features are known <strong>NOT</strong> to work with mapscript because they are not thread-safe.
     76                                Be sure not to enable them at compile time or you will get errors that will crash the JVM.
     77                                You can review the list of unsafe components <img src="/images/link-ext.gif" align="middle" /><a href="../../faq/thread_safety">here</a>.
     78                                </p>
     79</div>
     80<a name="N10079"></a><a name="Know+your+enemy+(part+2:+gdal+and+tiff)"></a>
     81<h4>Know your enemy (part 2: gdal and tiff)</h4>
     82<div>
     83<p>
     84                                If you need raster support through GDAL disable tiff (using <em>--without-tiff</em>) because they don't play well
     85                                with each other.
     86                                </p>
     87</div>
     88<a name="N10086"></a><a name="Know+your+enemy+(part+3:+pdf)"></a>
     89<h4>Know your enemy (part 3: pdf)</h4>
     90<div>
     91<p>
     92                                PDF is supported as an output format, but it is not worth the price of risking a buggy mapscript.
     93                                A better solution is to incorporate the image in a PDF document by using a pure Java library like the excellent
     94                                <em>iText</em>.
     95                                </p>
     96<p>
     97                                By doing so you will be able to customize headers, footers, paper format and transparencies will also work as supposed.
     98                                iText additionally supports PDF encryption to disallow printing, editing or modification.
     99                                </p>
     100<p>
     101                                Also remember that PDF output in mapserver cannot make use of an embedded scalebar because pixmap
     102                                fonts are not supported.
     103                                </p>
     104</div>
     105<a name="N10099"></a><a name="Know+your+enemy+(part+4:+connection+pooling)"></a>
     106<h4>Know your enemy (part 4: connection pooling)</h4>
     107<div>
     108<p>
     109                                Connection pooling is locked hence thread safe, but as of version 4.8.x (that is until Feb 2006)
     110                                it has known memory leaks. There is an issue on bugzilla that tracks this problem with Oracle.<br />
     111                               
     112<img src="/images/link-ext.gif" align="middle" /><a href="../../../bugs/show_bug.cgi?id=1662">http://mapserver.gis.umn.edu/bugs/show_bug.cgi?id=1662</a>.
     113                                </p>
     114<p>
     115                                Until that is cleared you can use connection pooling, just make sure that once in a while the application is
     116                                restarted or you will eventually run out of memory. How often this should happen depends on the number
     117                                of database connections defined in the map and the number of users. Sites with 1 or two database connections and
     118                                moderate to low use could reboot the application (that is the tomcat process in case of web apps) once a day.
     119                                </p>
     120<div class="frame note">
     121<div class="label">Note</div>
     122<div class="content">
     123                                There is no way to disable connection pooling.
     124                                </div>
     125</div>
     126<p>
     127                               
     128</p>
     129</div>
     130<a name="N100B2"></a><a name="Know+your+friends"></a>
     131<h4>Know your friends</h4>
     132<div>
     133<p>
     134                                Java Mapscript will <strong>NEVER</strong> work without the following configure flag: <em>--with-threads</em>.
     135                                Do not complain about you JVM going belly up on the mailing lists if you do not have enabled
     136                                this option.
     137                                </p>
     138</div>
     139<a name="N100C2"></a><a name="compile"></a>
     140<h4>The proper way to compile mapscript is...</h4>
     141<div>
     142<p>
     143                                To use mapserver and mapscript you will quite likely need to download and install
     144                                many other libraries and this might not particularly easy as most of
     145                                them (gdal, for instance) do not have a binary rpm for linux.<br />
     146                                You have then to find, download all of them and install one by one, solving
     147                                dependencies by hand. If this is not what you want and need a more portable
     148                                ,reliable and easier to deploy environment you should seriously consider
     149                                <img src="/images/link-ext.gif" align="middle" /><a href="http://fwtools.maptools.org/">fwtools</a>. Fwtools is collection of the most popular
     150                                libraries used with mapserver already compiled and ready to run on almost
     151                                any linux distribution.<br />
     152                               
     153<a href="#againstFwtools">This section</a> describes how to compile mapserver
     154                                and Java mapscript against fwtools.
     155                                </p>
     156<p>
     157                                The proper way to compile is to carefully select options as described above, then to run make,
     158                                cd into mapscript/java and run:
     159                                </p>
     160<pre class="code">make interface<br />make<br />make test<br />                         </pre>
     161<p>
     162                                Make interface requires that you have <img src="/images/link-ext.gif" align="middle" /><a href="http://www.swig.org">swig</a> installed, at least version 1.3.21.
     163                                </p>
     164<p>
     165                                My configure options to build mapscript with support for raster (through gdal), truetype fonts (through freetype),
     166                                shape files (native, cannot be disabled), projection (through proj) are:
     167                                </p>
     168<pre class="code">./configure --with-freetype --without-tiff --with-gdal=/opt/gdal/bin/gdal-config --with-proj --without-pdf --with-threads<br />                               </pre>
     169<p>
     170                                These are known to work (for me at least :-)) and are used in production sites. Note that proj, even
     171                                if it not used, is required for good operation of mapserver.
     172                                </p>
     173</div>
     174<a name="N100F2"></a><a name="againstFwtools"></a>
     175<h4>Compiling against fwtools</h4>
     176<div>
     177<p>
     178                                Download <img src="/images/link-ext.gif" align="middle" /><a href="http://fwtools.maptools.org/">fwtools</a> and install it. I usually install it in <em>/opt/FWTools-1.0.0b2</em>.
     179                                Cd into the lib subdirectory and run the following two commands:
     180                                </p>
     181<pre class="code">ln -s libpng.so.2 libpng.so<br />ln -s libfreetype.so.6 libfreetype.so<br />                          </pre>
     182<p>
     183                                This is required for mapserver configure script to find and use the freetype
     184                                and png libraries shipping with fwtools.
     185                                </p>
     186<p>
     187                                Download latest mapserver and unpack it, then compile it with the following
     188                                configuration:
     189                                </p>
     190<pre class="code">./configure --enable-debug --with-threads --without-pdf --without-tiff \<br />  --with-gdal=/opt/FWTools-1.0.0b2/bin/gdal-config --with-proj=/opt/FWTools-1.0.0b2/ \<br />  --with-gd=/opt/FWTools-1.0.0b2 --with-freetype=/opt/FWTools-1.0.0b2 \<br />  --with-png=/opt/FWTools-1.0.0b2 --with-zlib=/opt/FWTools-1.0.0b2 --with-jpeg=/opt/FWTools-1.0.0b2<br />                              </pre>
     191<p>
     192                                Before you run mapserver or mapscript make sure you load the fwtools environment by running
     193                                <em>/opt/FWTools-1.0.0b2/fwtools_env.sh</em>.
     194                                </p>
     195</div>
     196<a name="N10119"></a><a name="What's+the+deal+with+"></a>
     197<h4>What's the deal with make interface?</h4>
     198<div>
     199<p>
     200                                When I first used Java mapscript in 2003 running swig was a necessary prerequisite to
     201                                generate the Java and c wrapper files as the source distribution did not have any. There was a problem
     202                                though: swig would generate Java methods and c wrappers for all mapserver components (like postgis, wfs or ogr)
     203                                regardeless of the fact that they were enabled in the <em>configure</em> phase.
     204                                </p>
     205<p>
     206                                Then I submitted bug <img src="/images/link-ext.gif" align="middle" /><a href="../../../bugs/show_bug.cgi?id=876">#876</a> along with a patch which would
     207                                let swig know of which components were enabled and consequently generate Java and c wrappers only for them.
     208                                For the patch to work the user <strong>had to</strong> run make interface.
     209                                </p>
     210<p>
     211                                The problem then was that a rather new version of swig was required, which was not available on all distros
     212                                so the developers decided to provide a default version of the Java and c wrappers to help those who
     213                                did not have a recent swig (at least 1.3.21). That issue should be overcome by now as all
     214                                linux distros should ship with a swig version that is two years old!
     215                                <br />
     216                                So, if you have a recent version of swig (run <em>swig -version</em> to know) you should run make interface
     217                                to update your Java and c wrappers, even if the README does not recommend it.
     218                                </p>
     219</div>
     220</div>
     221               
     222<a name="N1013C"></a><a name="Running+Java+Mapscript+(on+Linux)"></a>
     223<h3>Running Java Mapscript (on Linux)</h3>
     224<div>
     225<p>
     226                        To correctly run any Java Mapscript application (be it a servlet, jsp page or a standalone graphical client)
     227                        you need to let the Java Virtual Machine know where to find two pieces of software:
     228                        </p>
     229<ol>
     230                               
     231<li>
     232                                       
     233<em>libmapscript.so</em> whose role is to tie together mapserver and Java</li>
     234                               
     235<li>
     236                                       
     237<em>mapscript.jar</em> which provides the mapserver Java objects which interface with libmapscript.so</li>
     238                       
     239</ol>
     240<p>
     241                        The location of the second must be specified on the classpath by means of the <em>CLASSPATH</em> environment variable
     242                        or the <em>-cp</em> option. The location of the first can be specified using the <em>LD_LIBRARY_PATH</em> variable or the
     243                        <em>-Djava.library.path</em> option. For an example see the <em>make test</em> command you ran after compiling mapscript.
     244                        </p>
     245<a name="N10166"></a><a name="Dealing+with+unresolved+dependencies"></a>
     246<h4>Dealing with unresolved dependencies</h4>
     247<div>
     248<p>
     249                                If your Java application brings up an error like the following:
     250                                </p>
     251<pre class="code">javac -classpath ./:examples/:./mapscript.jar -d examples/ examples/*.java<br />java -classpath ./:examples/:./mapscript.jar -Djava.library.path=. DumpShp ../../tests/point.shp<br />java.lang.UnsatisfiedLinkError: /opt-4.4.2/mapscript/java/libmapscript.so:<br />        libgdal.so.1: cannot open shared object file: No such file or directory<br />make: *** [test] Error 255<br />                           </pre>
     252<p>
     253                                it means that the gdal library was not found by the linker: this is probably due to the fact that gdal
     254                                was not supplied by your Linux distro and you installed it from source. In this case you must find the directory
     255                                where <em>libgdal.so.1</em> is and then add it to the <em>LD_LIBRARY_PATH</em> or the <em>-Djava.library.path</em>.
     256                                </p>
     257<a name="N10180"></a><a name="Specifying+the+library+name"></a>
     258<h5>Specifying the library name</h5>
     259<div>
     260<p>
     261                                        When the JVM attempts to load the shared library it will look by default for a file named <em>libmascript.so</em>
     262                                        in one of the system directories or in those specified by <em>LD_LIBRARY_PATH</em> or <em>-Djava.library.path</em>.<br />
     263                                        If necessary one can tell the JVM to load a shared library with a different name by passing the following
     264                                        argument to the <em>java</em> interpreter: <em>-Dmapserver.library.name=yourname</em>. For instance to load
     265                                        an hypothetical library named libmapscript-debug.so:
     266                                        </p>
     267<pre class="code">java -Dmapserver.library.name=mapscript-debug MyJavaProgram<br />                                     </pre>
     268</div>
     269</div>
     270</div>
     271               
     272<a name="N101A2"></a><a name="Learning+Java+Mapscript"></a>
     273<h3>Learning Java Mapscript</h3>
     274<div>
     275<p>
     276                        If you got this far then by now you probably want to know how to do X in Java Mapscript? (replace X with query, zoom, etc).
     277                        </p>
     278<p>
     279                        To date there is not a tutorial, nor code that you can look at (besides the examples, but that's not much frankly),
     280                        so the best thing you can do is take the php mapscript example form the mapserver web site and <em>translate</em> it
     281                        to Java. This is how I did the first time and somehow it worked.
     282                        </p>
     283<p>
     284                        Additional documentation is in the mapserver sources in <em>mapscript/doc</em>.
     285                        </p>
     286<a name="N101B7"></a><a name="QueryByPoint+example"></a>
     287<h4>QueryByPoint example</h4>
     288<div>
     289<p>
     290                                The following is an example of a working code snippets that opens a layer and queries
     291                                its features by shape. It has been used succesfully against shape and postgis sources.
     292                                </p>
     293<p>
     294                                Note the usage of the <img src="/images/link-ext.gif" align="middle" /><a href="http://jakarta.apache.org/commons/logging/">commons-logging</a> api for debuggins the code.
     295                                </p>
     296<pre class="code">protected List queryLayerByPoint(int i, pointObj queryPoint) {<br />   List results = new ArrayList();<br /><br />   layerObj layer = map.getLayer(i);<br />   if (layer != null &amp;&amp; isVisible(layer)) {<br />    if (log.isDebugEnabled()) {<br />               log.debug("Querying layer: " + layer.getName());<br />          }<br />         if (layer.queryByPoint(map, queryPoint,mapscript.MS_MULTIPLE, -1) == mapscript.MS_SUCCESS) {<br />              // OLD pre 4.2 code, see http://mapserver.gis.umn.edu/docs/howto/mapscript_querying<br />               //resultCacheObj resultCache = layer.ggetResultcache();<br />                   if (layer.open() == mapscript.MS_SUCCESS) {<br />                       // OLD pre 4.4 code<br />                       //for (int j=0;j &lt; resultCache.getNumresults();j++) {<br />                          for (int j = 0; j &lt; layer.getNumResults(); j++) {<br />                              if (log.isDebugEnabled())<br />                                         log.debug("Layer " + layer.getName() + ", result number:" + j);<br />                                   resultCacheMemberObj resultMember = layer.getResult(j);<br />                                   shapeObj shape = new shapeObj(layer.getType());<br />                                   layer.getShape(shape,resultMember.getTileindex(), resultMember.getShapeindex());<br />                                  if (shape != null) {<br />                                      Map aResult = getResult(shape, layer);<br /><br />                                      results.add(aResult);<br />                             } else {<br />                                          log.error("Shape " + j + " is null!");<br />                            }<br />                         }<br />                         layer.close();<br />            } else {<br />                          log.error("Cannot open layer: " + layer.getName());<br />               }<br />         } else {<br />                  log.info("Query on layer " + layer.getName() + " failed.");<br />       }<br />   }<br />   return results;<br />}<br />                             </pre>
     297</div>
     298</div>
     299               
     300<a name="N101CE"></a><a name="What+to+do+if+mapscript+crashes"></a>
     301<h3>What to do if mapscript crashes</h3>
     302<div>
     303<p>
     304                        Make sure that you have done all I have suggested here, in particular review the list
     305                        of unsafe components. After that try to isolate the piece of code that is
     306                        failing: if you cannot do that because errors are random then look for a <em>hs_err*.log</em> somewhere
     307                        in your filesystem. That is the file that the JVM creates when a crash occurs.
     308                        </p>
     309<p>
     310                        The file should report a stack trace that will tell you more or less exactly where the crash happened.
     311                        Review that piece of code and eventually ask on the mailing list. Before you ask on the mailing list
     312                        gather all information that you have available and that will be useful to diagnose the problem.
     313                        A good report should include:
     314                        </p>
     315<ul>
     316                               
     317<li>Linux version (both kernel and distro). Can be obtained by running: <em>uname -a</em>
     318                               
     319</li>
     320                               
     321<li>GCC Version: <em>gcc --version</em>
     322                               
     323</li>
     324                               
     325<li>mapserver version and compile flags: run <em>mapserv -v</em> and/or report the configure flags</li>
     326                               
     327<li>Java version and vendor: <em>java -version</em>
     328                               
     329</li>
     330                               
     331<li>swig version (if used): <em>swig -version</em>
     332                               
     333</li>
     334                               
     335<li>support libraries used and their version: gdal, proj, curl, postgis, etc</li>
     336                               
     337<li>whatever you think could help</li>
     338                       
     339</ul>
     340<p>
     341                        Additionally some will definitely find telling the reading of the venerable guide:
     342                        <img src="/images/link-ext.gif" align="middle" /><a href="http://www.catb.org/%7Eesr/faqs/smart-questions.html">how to ask questions the smart way</a>.
     343                        </p></div>
     344}}}