On 2/1/2011 2:30 PM, Christopher Dolan wrote:
My alternative solution to the same problem as Gregg's was to compute
SHA-1 hashes of the codebase jars, use that hash in the codebase URLs,
and aggressively cache the jars client-side via a custom
URLStreamHandlerFactory implementation instantiated in my
PreferredClassProvider subclass.  It works great -- it dramatically
reduced startup time after the first deployment and I no longer have to
worry too much about codebase jar sizes because I almost never need to
download them.  And it didn't require any code changes except in the
createLoader() method of my PreferredClassProvider subclass.

Even that first "deployment", for me, could not start downloading 100s of jar files. I did my vhttp: protocol handler for caching first, and it worked for my "small" early client deployments where only a single client interface was started and it would see 2-3 instances of the same service that it would list and let you pick one to access. The slow start up was still disliked and I heard about the issue from many techs. Even with a progress bar showing the downloading, indicating why it was not starting yet, they just said, we need to use the tool, not wait for it to download. I really wanted to use mobile code though because it make a tremendous difference in the difficulty of deploying bug fixes and updates. As picky as these people are, getting them to download and install an update was equally problematic.

In subsequent stages of evolution to the platform, I started adding a whole group of services/remote tools using Jini based discovery, so they could find an instance which was reachable, at one of multiple deployment locations. I needed to put all the tools into one "installed package" and a ServiceUI desktop was a great way to integrate access to all services.

But, now instead of 3 codebases to resolve, there were 30 or more (10-20 per machine). I just could not ask my customer to download all of that. I even pre-populated my vhttp: protocol handlers cache as one form of non-initial download handling. In the end, eliminating downloading until the service was requested was the only "complete" solution for me. Everything else just felt like a bandaid, where as this solution feels complete to me because it addresses the exact problem by not doing what is unnecessary. If I don't need to have a definition of a class from a remote server, then don't go there.

I'm glad to hear more about peoples customization of the service activation steps to learn how different solutions to the same problems I've had, have worked out.

Gregg

Chris

-----Original Message-----
From: Gregg Wonderly [mailto:gr...@wonderly.org]
Sent: Monday, January 31, 2011 7:30 PM
To: river-dev@incubator.apache.org
Subject: Re: MarshalledServiceItem

One of the important things for my use of my changes to the
ServiceRegistrar interface was separating deserialization of the Entrys
from the service object.  Ultimately, I wanted to not have to worry
about how the "codebase" was structured in order to minimize
downloading. Some Jini deployers have done things to put a small jar at
the front of the codebase that just has the preferred.list in it.  Even
that download, for me, would have been too much.  My customers'
deployments have nearly 50 codebases visible when my client starts up.
Those 50 connections over a cellular or other high latency network would
make service selection take way too long.

Being able to defer downloading was also controlled by the changes to
ClassLoading to include the "neverPrefer" settings on a class name.  I
can do that now through the recent RMIClassLoaderSPI override
capabilities.  But I still need to be able to control which Entry is
deserialized.  I need to be able to ask what classes, by name, are in
the namespace of each Entry object as my implementation allowed. I had
made changes to Reggie marshalling to use reflection to get the class
hierarchy, and then provided access to the list of classnames as part of
the returned, marshalled value in my API.

Gregg Wonderly

On Jan 30, 2011, at 2:23 PM, Peter Firmstone wrote:

Gut feel, tells me the following class is not right, it's intent is to
provide an api for implementation of delayed unmarshalling and
provisioning of codebases, for services implementing a lookup service or
ServiceRegistrar, whilst retaining backward compatibility.

In other words, the lookup service proxy would implement it.

Thoughts I had were to declare IOException's on methods, and to return
a String annotation, rather than a URI.

What are your thoughts?

Cheers,

Peter.

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.river.api.lookup;

import java.net.URI;
import java.security.CodeSource;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceID;
import net.jini.core.lookup.ServiceItem;

/**
* MarshalledServiceItem extends ServiceItem and can be used anywhere a
* ServiceItem can.  A MarshalledServiceItem implementation instance
* contains the marshalled form of a Service and it's Entry's,
* the corresponding superclass ServiceItem however contains null
values
* for the service and can exclude any Entry's, however where Entry
* classes already exist at the client, that they be unmarshalled.
*
* The ServiceID shall be in unmarshalled form always in the
ServiceItem super class.
*
* Since the ServiceItem.service is null, use of this class in existing
software
* will not return the service, however it will not break that software
as
* ServiceItem's contract is to set service or Entry's to null when
they cannot
* be unmarshalled.
*
* ServiceItem's toString() method will return a different result for
* MarshalledServiceItem instances.
*
* If required, a new ServiceItem that is fully unmarshalled
* can be constructed from this class's methods and ServiceID.
*
* @author Peter Firmstone.
*/
public abstract class MarshalledServiceItem extends ServiceItem{
   private static final long SerialVersionUID = 1L;
   protected MarshalledServiceItem(ServiceID id, Entry[]
unmarshalledEntries){
       super(id, (Object) null, unmarshalledEntries);
   }
   /**
    * Unmarshall the service proxy.
    * @param load service with local or existing CodeSource or null for
    * default.
    * @return the service proxy, null if class not found.
    */
   public abstract Object getService(CodeSource[] code);
   /**
    * Unmarshall the Entry's
    * @return array of Entry's, null entry in array for any class not
found.
    */
   public abstract Entry[] getEntries();
     public abstract URI[] getAnnotations();
}




Reply via email to