Gregg Wonderly wrote:
On 2/2/2011 6:15 PM, Peter Firmstone wrote:
Michał Kłeczek wrote:
On Thu, Feb 3, 2011 at 12:47 AM, Peter Firmstone <[email protected]>
wrote:
I like the fact that Gregg's pushed the envelope, he's pushed Jini
beyond
it's current capability.
Now I'm wondering if there's a way around the Preferred Classes
problem.
The problem with PREFERRED.LIST is more fundamental - for example
every RemoteEvent producer is forced to download a jar file just to
check that RemoteEventListener is not preferred. As such the issue
cannot be solved at the LUS API level.
Michal
Yes there are more fundamental problems with preferred classes,
ClassLoading etc
that remain to be solved.
But rather than fix it on this occassion, MarshalledServiceItem is
just resolved
with local classes and preferred class loading is not used or needed.
When the
client unmarshalls the MarshalledServiceItem, then preferred class
loading will
be used and jar files downloaded. MarshalledServiceItem can provide a
significant amount of information by just resolving using local
classes, which
the client can utilise.
In the long term I see it like this:
We need to look into dependency inversion to remove implementation
classes from
the platform and application class loader, which is the problem that
preferred
class loading addresses.
If implementation classes are not present in the platform, you don't
need
preferred classes for proxys to have their own copy of an
implementation class,
because those classes will be resolved by standard java classloading
rules in
the proxy class loader.
One thing to note, is that I have used PreferredClassLoader to fix
bugs by taking common classes that I use in GUI constructions that
would have been resolved in the parent loader and switching them to be
preferred so that I'd get the fixed version. I am not sure that there
is a perfect "split" of implementation vs platform. Sometimes
implementation can be a mini-platform of sorts. Just
repackaging/rearranging jars is not a singular fix, always.
Gregg Wonderly
Based on our discussions, I've made changes to MarshalledServiceItem and
StreamServiceRegistrar (see below), I have reduced
StreamServiceRegistrar to a single lookup method, my reasoning is, the
other methods, based on those already existing in ServiceRegistrar, are
there primarily to build a suitable ServiceTemplate to avoid downloading
proxy's, however since we're providing an alternate means
(MarshalledServiceItem) to avoid or delay downloading proxy's those 3
methods are less relevant.
So what we have is a new lookup service interface for the internet, that
extends ServiceRegistrar and provides one new method, with means to
provide Entry's that resolve locally for querying without downloading
any jar files, until such time as the client wants to, this could also
avoid downloading the MarshalledInstance of the proxy until
unmarshalling is performed.
In summary MarshalledServiceItem is a class that only resolves local
code. Interestingly MarshalledServiceItem, might not be an appropriate
name, perhaps LocalServiceItem to indicate that only local code is
utilised, on this reasoning, I can't see any objection to reflective
proxy's being non null either.
What ramifications does this have for proxy trust if we already trust
the lookup service?
MarshalledServiceItem's single method, unmarshall, is not declared to
throw an IOException or remote exception, for the case where a
ServiceItem cannot be unmarshalled, fields are set to null, as is the
current practice for ServiceItem. Does anyone think this method should
declare any exceptions?
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);
}
/* Default constructor for serializable sub class.
*/
protected MarshalledServiceItem(){
super(null, null, null);
}
/**
* Unmarshall the ServiceItem. The returned ServiceItem may have a
null service
* or entries , if unmarshalling is unsuccessful.
*
* @return ServiceItem, totally unmarshalled.
*/
public abstract ServiceItem unmarshall();
}
/*
* 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.io.IOException;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.core.lookup.ServiceItem;
import org.apache.river.api.util.ResultStream;
/**
* Defines the interface to the lookup service. The interface is not a
* remote interface; each implementation of the lookup service exports
* proxy objects that implement the StreamServiceRegistrar interface
local to
* the client, using an implementation-specific protocol to communicate
* with the actual remote server. All of the proxy methods obey normal
* RMI remote interface semantics except where explicitly noted. Two
* proxy objects are equal if they are proxies for the same lookup service.
* Every method invocation (on both StreamServiceRegistrar and
ServiceRegistration)
* is atomic with respect to other invocations.
*
* The StreamServiceRegistrar is intended to perform the same function
* as the ServiceRegistrar, but with the ability to return results as a
* stream, so memory consumption can be minimised at the client.
*
* All clients utilising ServiceRegistrar, should switch to the
* StreamServiceRegistrar.
*
* @see ServiceRegistrar
* @see PortableServiceRegistrar
* @see ServiceRegistration
* @author Peter Firmstone
* @since 2.2.0
*/
public interface StreamServiceRegistrar extends ServiceRegistrar{
/**
* Returns a ResultStream that provides access to MarshalledServiceItem
* instances. The ResultStream terminates with a null value. The
result
* stream may be infinite.
*
* 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 excludes any Entry's that are not
specifically requested
* unmarshalled by this method. The ServiceID will be unmarshalled
always.
*
* This method is designed to allow the caller to control exactly what
* is unmarshalled and when, it allows unmarshalling of specific entries
* that the caller may wish to utilise for filtering. It is
* designed to allow both the caller and the implementer to deal
with very
* large result sets in an incremental fashion.
*
* It is absolutely essential that the caller closes and deletes any
references to
* the returned result stream as soon as it is no longer requried.
*
* @param tmpl template to match
* specified template
* @param unmarshalledEntries only Entry's with these classes will be in
* unmarshalled form.
* @param maxBatchSize Allows the caller to limit the number of results
* held locally, larger batch sizes reduce network traffic, but may
delay
* processing locally depending on implementation.
* @return ResultStream containing ServiceItem's
* @throws java.rmi.RemoteException
* @see MarshalledServiceItem
* @see ServiceItem
* @see ResultStream
* @see ServiceResultStreamFilter
* @see ResultStreamUnmarshaller
* @since 2.2.0
*/
ResultStream lookup(ServiceTemplate tmpl,
Class[] unmarshalledEntries, int maxBatchSize) throws IOException;
}