Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [udig-devel] Creating own renderer

I'll start by adding a better logging method to BasicFeatureRenderer.  With regards to your error.  It is a strange one.  WFSFilterVisitor parses the query filter to obtain the bbox of the request.  But I can't think of any reason that is would work with the normal renderer and not yours.  Could you extend the BasicFeatureRenderer ala the ShapefileRenderer.  That why there would be less potential for errors. 

Mark Presling wrote:
I'm starting to get somewhere...

I have just found that the error handling in the render() method is to blame for most of the time that I have spent trying to figure this out. An exception has been getting swallowed. Adding this to the end of the render() method:
        }finally{
            if (listener.exception != null) {
            --> listener.exception.printStackTrace(); <--
                if (!(listener.exception instanceof TopologyException)){
  
produces:
RoadEventFeatureRenderer.render()
java.lang.Exception: Exception rendering layer DefaultMapLayer[ Test, VISIBLE, style=StyleImpl<NO_PARENT.styles[0]>[ name=Default Styler], data="" query=Query:
   feature type: topp:roadevent_pnt
   filter: Filter.ALL
   [properties:  ALL ]]
	at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:503)
	at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:407)
	at net.refractions.udig.render.internal.feature.basic.RoadEventFeatureRenderer.render(RoadEventFeatureRenderer.java:195)
	at net.refractions.udig.render.internal.feature.basic.RoadEventFeatureRenderer.render(RoadEventFeatureRenderer.java:162)
	at net.refractions.udig.project.internal.render.impl.RenderExecutorImpl$RenderJob.startRendering(RenderExecutorImpl.java:273)
	at net.refractions.udig.project.internal.render.impl.RenderExecutorImpl$RenderJob.run(RenderExecutorImpl.java:334)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:76)
Caused by: java.util.EmptyStackException
	at java.util.Stack.peek(Stack.java:79)
	at java.util.Stack.pop(Stack.java:61)
	at org.geotools.data.wfs.WFSFilterVisitor.visit(WFSFilterVisitor.java:161)
	at org.geotools.filter.Filter$2.accept(Filter.java:99)
	at org.geotools.data.wfs.WFSDataStore.splitFilters(WFSDataStore.java:882)
	at org.geotools.data.wfs.WFSDataStore.getFeatureReader(WFSDataStore.java:708)
	at org.geotools.data.DefaultFeatureResults.reader(DefaultFeatureResults.java:147)
	at org.geotools.renderer.lite.StreamingRenderer.getReader(StreamingRenderer.java:957)
	at org.geotools.renderer.lite.StreamingRenderer.processStylers(StreamingRenderer.java:1055)
	at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:501)
	... 6 more

  
And on the GeoServer side I discovered this deep down in the log:
1841446948 [INFO] org.vfny.geoserver.wfs.servlets.WfsDispatcher - req_type is -1
1841446949 [WARNING] org.vfny.geoserver.ServiceException - encountered error: No request recognized.  The REQUEST parameter must be one of GetFeature, GetFeatureWithLock, DescribeFeatureType, LockFeature, or Transaction.
StackTrace: org.vfny.geoserver.wfs.WfsException: No request recognized.  The REQUEST parameter must be one of GetFeature, GetFeatureWithLock, DescribeFeatureType, LockFeature, or Transaction.
        at org.vfny.geoserver.wfs.servlets.WfsDispatcher.doResponse(WfsDispatcher.java:305)
        at org.vfny.geoserver.wfs.servlets.WfsDispatcher.doGet(WfsDispatcher.java:213)

  
So... once again... can anyone think of a reason for this happening when I use my own MetricsFactory defined in the extension point (see previous email(s) for more information on what I have done)? As I said previously, when I modify the BasicFeatureMetricsFactory to return my renderer it works fine. But when I point the renderer extension point at my own MetricsFactory (which is an almost exact copy of BasicFeatureMetricsFactory) it errors out.

I guess the first thing to take from this is that someone needs to look at the error handling in the render() method, because it swallowed the exceptions even when tracing and -consoleLog was turned on.

Thanks in advance,
Mark

Mark Presling wrote:
Hi Jesse,

This just gets wierder...

The style is fine. I have done all sorts of validation on it (and found that the style editor tool creates invalid SLD by default when you validate it with it's own validator - which I know you are working on). And it does work... see below.

After aother day of head banging and debugging I just tried something new. I modified BasicFeatureMetricsFactory and BasicFeatureMetrics to return my renderer instead of BasicFeatureRenderer, and guess what... it worked!

So I can confirm that my renderer does actually work (because it's an exact copy of BasicFeatureRenderer, it's just that when I use my own Metrics and MetricsFactory classes in the extension it does not. Even when I remove the extension definition for BasicFeatureMetricsFactory it still doesn't render anything on the map.

I have even tried to put my classes in the render.feature.basic plugin to make sure it's not a classloading issue or something.

Here are the Metrics classes:

package net.refractions.udig.render.internal.feature.basic;

import net.refractions.udig.project.internal.render.SelectionLayer;
import net.refractions.udig.project.render.IRenderContext;
import net.refractions.udig.project.render.IRenderMetrics;
import net.refractions.udig.project.render.IRenderMetricsFactory;
import net.refractions.udig.project.render.IRenderer;

import org.geotools.data.FeatureSource;

public class RoadEventFeatureMetricsFactory implements IRenderMetricsFactory {

   /**
    * @see net.refractions.udig.project.render.IRenderMetricsFactory#createMetrics(net.refractions.udig.project.render.IRenderContext)
    */
   public IRenderMetrics createMetrics(IRenderContext context) {
       return new RoadEventFeatureMetrics(context, this);
   }

   /**
    * @see net.refractions.udig.project.render.IRenderMetricsFactory#canRender(net.refractions.udig.project.render.IRenderContext)
    */
   public boolean canRender( IRenderContext context ) {
       try {
           FeatureSource fs = context.getGeoResource().resolve(FeatureSource.class, null);
           String layerName = context.getLayer().getName();
           if (context.getLayer() instanceof SelectionLayer && fs != null) {// && "roadevent_pnt".equalsIgnoreCase(layerName)
               System.err.println("RoadEventFeatureMetricsFactory returning true for " + layerName);
               return true;
           }
                      System.err.println("RoadEventFeatureMetricsFactory returning false for " + layerName);
           return false;
       } catch (Throwable t) {
           t.printStackTrace();
           return false;
       }
   }

   /**
    * @see IRenderMetricsFactory#getRendererType()
    */
   public Class<? extends IRenderer> getRendererType() {
       return RoadEventFeatureRenderer.class;
   }
}


package net.refractions.udig.render.internal.feature.basic;

import net.refractions.udig.project.ILayer;
import net.refractions.udig.project.internal.render.Renderer;
import net.refractions.udig.project.render.IRenderContext;
import net.refractions.udig.project.render.IRenderMetrics;
import net.refractions.udig.project.render.IRenderMetricsFactory;

import org.geotools.styling.Style;

public class RoadEventFeatureMetrics implements IRenderMetrics {

   private IRenderContext context;
   private RoadEventFeatureMetricsFactory factory;

  /**
    * Construct <code>RoadEventFeatureMetrics</code>.
    *
    * @param context2
    * @param factory
    */
   public RoadEventFeatureMetrics( IRenderContext context2, RoadEventFeatureMetricsFactory factory ) {
       this.context=context2;
       this.factory=factory;
   }


   /**
    * @see net.refractions.udig.project.render.IRenderMetrics#createRenderer()
    */
   public Renderer createRenderer() {
       Renderer renderer=new RoadEventFeatureRenderer();
       renderer.setContext(context);
       renderer.setName(context.getLayer().getName());
       return renderer;
   }

   /**
    * @see net.refractions.udig.project.render.IRenderMetrics#getRenderContext()
    */
   public IRenderContext getRenderContext() {
       return context;
   }

   /**
    * @see net.refractions.udig.project.render.IRenderMetrics#getRenderMetricsFactory()
    */
   public IRenderMetricsFactory getRenderMetricsFactory() {
       return factory;
   }

   public boolean canAddLayer( ILayer layer ) {
       return true;
   }

   public boolean canStyle( String SyleID, Object value ) {
       return value != null && value instanceof Style;
   }


   public boolean isOptimized() {
       return false;
   }

}


Any more ideas? Has anyone else out there implemented their own renderer and noticed any strange behaviour like this?

Thanks,
Mark

ps I like the Theme part of the SLD editor... very cool!


Jesse Eichar wrote:

Nothing is jumping out at me right away.  Maybe the style is somehow crazy?  Seems unlikely but possible.  Could you send the style to us?

Jesse

Mark Presling wrote:

Hi. Sorry to bug the list again, but I have been trying to create my own renderer based on BasicFeatureRenderer to render the features of a WFS layer.

What I have done is this:

   1. Make a copy of BasicFeatureRenderer called
      RoadEventFeatureRenderer. The only thing different at this
      stage is the name and package
   2. Make a copy of BasicFeatureMetricsFactory called called
      RoadEventFeatureMetricsFactory. The differences are the
      name/package, what it returns in createMetrics() and and
      getRendererType() and a check in canRender() that returns true
      only for a particular layer name

           String layerName = context.getLayer().getName();
           String layerName = context.getLayer().getName();if (context.getLayer() instanceof SelectionLayer && fs != null && *"roadevent_pnt".equalsIgnoreCase(layerName)*) {
               System.err.println("RoadEventFeatureMetricsFactory returning true for " + layerName);
               return true;
           }
  
   3. Make a copy of BasicFeatureMetrics called called
      RoadEventFeatureMetrics. Changed types to match those above.
   4. Modify BasicFeatureMetricsFactory to return false for the
      particular layer identified above.
   5. Register my renderer with the extension point
      net.refractions.udig.project.renderer in my plugin.xml

<extension
        point="net.refractions.udig.project.renderer">
     <renderer class="nz.govt.transit.callcenter.RoadEventFeatureMetricsFactory"/>
  </extension>

   6. Run app.

What I find through debugging is that the renderer is called as expected, but for some reason it is not outputting anything. Please note that I have not modified the actual rendering code... it still uses the StreamingRenderer as the existing one does.

I have noticed that the filter/queries that are set on the layer are different to the ones set when using BasicFeatureRenderer. In BFR the filter is:

Query: [Request All Features]
  feature type: null
  filter: Filter.NONE
  [properties:  ALL ]
 

but in mine it was Filter.ALL (which I believe means filter OUT everything - return nothing). So I explicitly set the query to Query.ALL in the setQueries() method of my BFR clone.

So, this meant that the feature collection returned in the StreamingRenderer had 24 items in it now. Good. However, still nothing is rendered and when you click on the layer it says "Layer not rendered" in the status bar.

Another thing of concern is that on the console I see this:

Current Renderers:
    CompositeRendererImpl
    RenderExecutorImpl:BasicWMSRenderer2-highway
    RenderExecutorImpl:BasicFeatureRenderer-nmcregion_poly
 

I have 1 WMS layer and 2 WFS layers - one of which I want to render with my renderer. As you can see, my renderer doesn't appear in this list, but it is definitely instantiated and the render method is definitely called on it.

Is there something that I am missing in terms of extensions or classes that I need to implement? My intention is to just implement a renderer, not the whole stack of DataSource/FeatureSource/etc.

Thanks,
Mark

-- 
This message has been scanned for viruses and dangerous
content by *MailScanner* <http://www.mailscanner.info/>*, and is believed to be clean. *

*_______________________________________________
User-friendly Desktop Internet GIS (uDig)
http://udig.refractions.net
http://lists.refractions.net/mailman/listinfo/udig-devel
 *

*

-- 
This message has been scanned for viruses and dangerous
content by *MailScanner* <http://www.mailscanner.info/>, and is believed to be clean. *

*
*
------------------------------------------------------------------------
*
_______________________________________________
User-friendly Desktop Internet GIS (uDig)
http://udig.refractions.net
http://lists.refractions.net/mailman/listinfo/udig-devel
*


_______________________________________________
User-friendly Desktop Internet GIS (uDig)
http://udig.refractions.net
http://lists.refractions.net/mailman/listinfo/udig-devel
  

--
This message has been scanned for viruses and dangerous
content by MailScanner, and is believed to be clean.
_______________________________________________
User-friendly Desktop Internet GIS (uDig)
http://udig.refractions.net
http://lists.refractions.net/mailman/listinfo/udig-devel
  


Back to the top