web services issue in code first approach - web-services

Hi I am new to Web Services, I have the requirement of Code First Approach,
I have an interface like below
package in.co.way2learn;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
#WebService(name="SQS",portName="SQSP",serviceName="SQSS")
public interface StockQuoteService {
#WebMethod(operationName="getPrice")
public double getPrice(#WebParam(name="symbol")String symbol);
#WebMethod(operationName="aaa",action="aaaAction")
public boolean update(#WebParam(name="sybmol")String symbol,#WebParam(name="price")double price);
#WebMethod(operationName="bbb",action="bbbAction")
public boolean update(#WebParam(name="sybmol")String symbol,#WebParam(name="price")double price,#WebParam(name="flag")boolean flag);
}
I want to expose an implementation if the the above interface as web service.
The implementation class is as below:
package in.co.way2learn;
import javax.jws.WebMethod;
import javax.jws.WebService;
#WebService(name="SQSI",
endpointInterface="in.co.way2learn.StockQuoteService",
portName="SQSIP",serviceName="SQSIS")
public class StockQuoteServiceImpl implements StockQuoteService{
#Override
public double getPrice(String symbol) {
System.out.println("StockQuoteServiceImpl.getPrice()");
return 123;
}
#Override
#WebMethod(operationName="aaa",action="aaaAction")
public boolean update(String symbol, double price) {
System.out.println("StockQuoteServiceImpl.update()");
return true;
}
#Override
#WebMethod(operationName="bbb",action="bbbAction")
public boolean update(String symbol, double price, boolean flag) {
System.out.println("StockQuoteServiceImpl.update()");
return true;
}
}
To expose this service as web service I am using JDK's EndPoint class as below.
package in.co.way2learn;
import javax.xml.ws.Endpoint;
public class Server {
public static void main(String[] args) {
StockQuoteService stockQuoteService=new StockQuoteServiceImpl();
String address="http://localhost:8080/sqs";
Endpoint.publish(address, stockQuoteService);
System.out.println("Server started..!");
}
}
But When I run the server program I am getting the following exception.
Exception in thread "main" javax.xml.ws.WebServiceException: class in.co.way2learn.jaxws.Update do not have a property of the name flag
at com.sun.xml.internal.ws.server.sei.EndpointArgumentsBuilder$DocLit.<init>(Unknown Source)
at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.createArgumentsBuilder(Unknown Source)
at com.sun.xml.internal.ws.server.sei.EndpointMethodHandler.<init>(Unknown Source)
at com.sun.xml.internal.ws.server.sei.SEIInvokerTube.<init>(Unknown Source)
at com.sun.xml.internal.ws.server.EndpointFactory.createEndpoint(Unknown Source)
at com.sun.xml.internal.ws.api.server.WSEndpoint.create(Unknown Source)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.createEndpoint(Unknown Source)
at com.sun.xml.internal.ws.transport.http.server.EndpointImpl.publish(Unknown Source)
at com.sun.xml.internal.ws.spi.ProviderImpl.createAndPublishEndpoint(Unknown Source)
at javax.xml.ws.Endpoint.publish(Unknown Source)
at in.co.way2learn.Server.main(Server.java:10)
Caused by: javax.xml.bind.JAXBException: flag is not a valid property on class in.co.way2learn.jaxws.Update
at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getElementPropertyAccessor(Unknown Source)
... 11 more
Here in StockQuoteService interface and corresponding implementation I have two overloaded update method one is taking two parameters while other is taking three.
If I change second update method name to different name, then the server is running fine without exception.
But exception is coming when i have overloaded update methods only.
Even though I kept overloaded methods, their operation names and corresponding soap actions are different, you can see them in annotations on top of the methods.
Any help will give me great relief and appreciated as well.

Related

How do I mock creating a connection to HBase in a constructor?

I am trying to set up my unit tests so that I can test my HBase Client. However, I am having trouble mocking the creation of the connection to HBase in the constructor. I don't think I am correctly injecting the mocked connection into the class I want to test, but I'm not sure where I made the mistake. I've looked at similar questions about mocking a connection, but all of those have the creation of the connection outside of the constructor.
This is the code I am trying to test:
#Lazy
#Service("HBaseClient")
public class HBaseClient {
/**
* Instantiate a new client and create connection to HBase.
*/
public HBaseClient() {
// Create connection to HBase
conf = HBaseConfiguration.create();
conf.setInt("timeout", 120000);
conf.set("hbase.zookeeper.quorum", zookeeperHost);
conf.set("hbase.zookeeper.property.clientPort", zookeeperPort);
conf.set("zookeeper.znode.parent", znodeParent);
try {
connection = ConnectionFactory.createConnection(conf);
} catch (IOException e) {
logger.error("Error creating connection to HBase - IOException");
}
}
public void addRecord(String rowKey, String columnFamily, Map<String, String> values) {
...
Here is what I have in the unit test:
#RunWith(PowerMockRunner.class)
public class TestHBaseClient {
#InjectMocks
private static HBaseClient hbaseClient;
#BeforeClass
#PrepareForTest({ConnectionFactory.class})
public static void setUpBeforeClass() throws Exception {
Connection mockConnection = PowerMockito.mock(Connection.class);
PowerMockito.mockStatic(ConnectionFactory.class);
PowerMockito.when(ConnectionFactory.createConnection()).thenReturn(mockConnection);
hbaseClient = new HBaseClient();
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
#Test
public void testAddRecord() {
HashMap<String, String> values = new HashMap<String, String>();
values.put("test1", "abc");
values.put("test2", "xyz");
hbaseClient.addRecord("test", "Test", values);
}
}
The code as it currently is throws the following error:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
when(mock.getArticles()).thenReturn(articles);
Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public. It is a limitation of the mock engine.
at org.powermock.api.mockito.PowerMockito.when(PowerMockito.java:495)
at
com.rtn.cdp.storage.hbase.test.TestHBaseDataClient.setUpBeforeClass(TestHBaseClient.java:32)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498) at
org.junit.internal.runners.ClassRoadie.runBefores(ClassRoadie.java:56)
at
org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:43)
at
org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
at
org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101)
at
org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at
org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at
org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

Spring cloud with RDS, hello world

I am newbie to Spring Cloud and wanted to write a simple "hello world" RDS program.
My configuration is stored in the xml config as follows.
<aws-context:context-credentials>
...
</aws-context:context-credentials>
<aws-context:context-region region="ap-southeast-1" />
<jdbc:data-source db-instance-identifier="amazonrds"
password="${password}" read-replica-support="false">
<jdbc:pool-attributes initialSize="1"
defaultCatalog="Records" testOnBorrow="true" validationQuery="SELECT 1" />
</jdbc:data-source>
And I have a simple DB service class which reads like this.
#Service
public class JdbcRecordService implements RecordService {
private final JdbcTemplate jdbcTemplate;
#Autowired
public JdbcRecordService(DataSource datasource) {
this.jdbcTemplate = new JdbcTemplate(datasource);
}
#Override
#Transactional(readOnly = true)
public List<Record> all() {
return this.jdbcTemplate.query("SELECT * FROM Records", new RowMapper<Record>() {
#Override
public Record mapRow(ResultSet resultSet, int rowNum) throws SQLException {
return new Record(resultSet.getString("Name"), resultSet.getString("Value"));
}
});
}
#Override
#Transactional
public void store(Record record) {
this.jdbcTemplate.update("INSERT INTO Records(Name, Value) VALUES (?,?)", record.getKey(), record.getValue());
}
}
And the Application class is like this.
#SpringBootApplication
#EnableAutoConfiguration
#Configuration
#ComponentScan
#ImportResource("classpath:aws-config.xml")
public class SpringBootAwsApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootAwsApplication.class, args);
}
}
I know I am missing some connectors here, but I can't figure out what it is. Currently it throws this error, when building.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jdbcRecordService' defined in file [C:\Users\codev\gitlab\springaws\target\classes\base\rds\JdbcRecordService.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [org.apache.tomcat.jdbc.pool.DataSource]: : No qualifying bean of type [org.apache.tomcat.jdbc.pool.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [org.apache.tomcat.jdbc.pool.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
It basically says, there is no bean candidate that can autowire the construction with a DataSource parameter. What am I missing here?
EDIT:My issue got fixed just by re-ordering the depending in my POM.xml. I still don't know which specific dependency conflict caused this issue but just moving aws-java-sdk to the top of the dependency list fixed my issues.

Enum conversion to String not working on #Indexed unique field

I'm a Neo4j/Spring-data newbie so apologies if this is something obvious but I looked here and there and can't quite figure out if it's a bug or feature.
I'm using SDN 3.1.0 and Neo4j 2.0.4, running in memory for now (for testing).
I have a super simple POJO that I try to save into Neo4j using SDN. It looks like so:
#NodeEntity
public class Weekday {
#GraphId
private Long id;
#Indexed(unique = true)
public DayOfWeek weekdayCode;
}
Everything works beautifully when I make it non-uniquely indexed, or not indexed at all. It works fine with unique constraint when I make it a String as well. (Well, sort of, I'm aware that it doesn't throw an exception but silently updates existing one - this is not perfect but I found JIRA issue related to that). Unfortunately the moment I try to save it as enum with unique constraint I get an exception:
org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props} return n; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props} return n; nested exception is java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.query(CypherQueryEngineImpl.java:61)
at org.springframework.data.neo4j.support.schema.SchemaIndexProvider.merge(SchemaIndexProvider.java:114)
at [...]
Caused by: org.springframework.dao.InvalidDataAccessResourceUsageException: Error executing statement MERGE (n:`Weekday` {`weekdayCode`: {value}}) ON CREATE SET n={props} return n; nested exception is java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.parseAndExecuteQuery(CypherQueryEngineImpl.java:72)
at org.springframework.data.neo4j.support.query.CypherQueryEngineImpl.query(CypherQueryEngineImpl.java:58)
... 63 more
Caused by: java.lang.IllegalArgumentException: [MONDAY:java.time.DayOfWeek] is not a supported property value
at org.neo4j.kernel.api.properties.PropertyConversion.convertProperty(PropertyConversion.java:107)
at org.neo4j.kernel.api.properties.Property.property(Property.java:51)
at [...]
This, as far as I can see, is because the unique field is put into a map "props", and the contents of the map is not automatically converted so it sends an enum to Neo4j, which obviously it doesn't like.
Is this expected or should I raise a bug with SDN?
If that's expected behaviour, do I have any alternatives other than making the field a String?
I'm not sure if it is a real bug, however I had a similar problem using my own Enum class.
So, you could try something like this:
Create the converters
Register them in neo4j
First create your converters like:
#Component
public class StringToDayOfWeekConverter implements Converter<String, DayOfWeek> {
#Override
public DayOfWeek convert(String source) {
return DayOfWeek.valueOf(source);
}
}
#Component
public class DayOfWeekToStringConverter implements Converter<DayOfWeek, String> {
#Override
public String convert(DayOfWeek source) {
return source.name();
}
}
Then you register the converters, so neo4j can use them:
#Configuration
#EnableNeo4jRepositories("my.repository.package")
#EnableTransactionManagement
public class MyNeo4jConfiguration extends Neo4jConfiguration {
#Autowired
private StringToDayOfWeekConverter stringToDayOfWeekConverter;
#Autowired
private DayOfWeekToStringConverter dayOfWeekToStringConverter;
#Override
protected ConversionService neo4jConversionService() throws Exception {
ConverterRegistry converterRegistry = (ConverterRegistry) super.neo4jConversionService();
converterRegistry.addConverter(stringToDayOfWeekConverter);
converterRegistry.addConverter(dayOfWeekToStringConverter);
return (ConversionService) converterRegistry;
}
}
create an converter extends EnumStringConverter such like this:
package com.noopu.pyramid.domain.model.converter;
import com..pyramid.common.UserType;
import org.neo4j.ogm.typeconversion.EnumStringConverter;
public class UserTypeStringConverter extends EnumStringConverter {
public UserTypeStringConverter ( ) {
super ( UserType.class );
}
}
and used #Converter annotation like under:
package com.noopu.pyramid.domain.model;
import com.noopu.pyramid.common.UserType;
import com.noopu.pyramid.domain.model.converter.UserTypeStringConverter;
import lombok.Data;
import org.neo4j.ogm.annotation.GraphId;
import org.neo4j.ogm.annotation.Index;
import org.neo4j.ogm.annotation.NodeEntity;
import org.neo4j.ogm.annotation.typeconversion.Convert;
import java.io.Serializable;
#NodeEntity
#Data
public class User implements Serializable {
private static final long serialVersionUID = 8979348201709416439L;
#GraphId
private Long graphId;
#Index
protected Long id;
#Index(unique = true)
private Long uid;
#Index(unique = true)
private String phone;
#Index
#Convert(UserTypeStringConverter.class)
private UserType type;
}

ConstraintViolationException in Java RESTful Webservice

I'm relatively new to JavaEE and web services, however, I'm using netbeans to generate my client and webservice resources. I have a resource "CustomerData" that represents a mysql database table and a value "rewardsPoints" representing a column in that table, however, I am unable to update the value due to a ConstraintViolationException, specifically:
javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'preUpdate'. Please refer to embedded ConstraintViolations for details.
I'm not familiar with the 'preUpdate' callback event, is it something I need to override? I can't seem to figure out exactly why this exception is being thrown, but, as I said, i'm very new to web service programming. Here are my classes:
#Stateless
#Path("customers")
public class CustomerDataFacadeREST extends AbstractFacade<CustomerData> {
#PersistenceContext(unitName = "CustomerPortalPU")
private EntityManager em;
public CustomerDataFacadeREST() {
super(CustomerData.class);
}
#PUT
#Path("{id}")
#Consumes({"application/xml", "application/json"})
public void edit(#PathParam("id") Integer id, CustomerData entity) {
super.edit(entity);
}
#GET
#Path("{id}")
#Produces({"application/xml", "application/json"})
public CustomerData find(#PathParam("id") Integer id) {
return super.find(id);
}
#GET
#Path("addPoints/{id}/{amount}")
#Produces({"text/plain"})
public String addPoints(#PathParam("id") Integer id, #PathParam("amount") int amount) {
CustomerData customer = find(id);
customer.getRewardsPoints(customer.getRewardsPoints() + amount);
em.persist(customer);
edit(customer);
return customer.getRewardsPoints();
}
#Override
protected EntityManager getEntityManager() {
return em;
}
}
And the CustomerData entity class:
#Entity
#Table(name = "tbl_customer_data")
#XmlRootElement
public class CustomerData implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Basic(optional = false)
#Column(name = "id")
private Integer id;
#Basic(optional = false)
#NotNull
#Column(name = "rewards_points")
private int rewardsPoints;
public CustomerData(Integer id, int rewardsPoints) {
this.id = id;
this.rewardsPoints = rewardsPoints;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public int getRewardsPoints() {
return rewardsPoints;
}
public void setRewardsPoints(int rewardsPoints) {
this.rewardsPoints = rewardsPoints;
}
}
When I try to access the URI:
http://localhost:8080/CustomerPortal/ws/customers/addPoints/1/5
to add 5 points to user with id 1 i get an HTTP 500 error and in the glassfish logs it says
[2013-11-05T03:28:11.733-0500] [glassfish 4.0] [WARNING] [ejb.system_exception] [javax.enterprise.system.container.ejb.com.sun.ejb.containers] [tid: _ThreadID=21 _ThreadName=http-listener-1(3)] [timeMillis: 1383640091733] [levelValue: 900] [[
EJB5184:A system exception occurred during an invocation on EJB CustomerDataFacadeREST, method: public java.lang.String com.webservice.entities.CustomerDataFacadeREST.addPoints(java.lang.Integer,int)]]
[2013-11-05T03:28:11.741-0500] [glassfish 4.0] [WARNING] [] [javax.enterprise.web] [tid: _ThreadID=21 _ThreadName=http-listener-1(3)] [timeMillis: 1383640091741] [levelValue: 900] [[
StandardWrapperValve[com.webservice.entities.ApplicationConfig]: Servlet.service() for servlet com.webservice.entities.ApplicationConfig threw exception
javax.validation.ConstraintViolationException: Bean Validation constraint(s) violated while executing Automatic Bean Validation on callback event:'preUpdate'. Please refer to embedded ConstraintViolations for details.
Any resources, insight or information regarding this issue would be extremely helpful.
The exception has little to do with web services: it has to do with Bean Validation instead.
In this case, since the Validation fails inside method addPoints (look at the stack trace) the only line that can cause it is when persisting or editing an Entity of type CustomerData. The only constraint you have in that class is that rewardsPoints should not be null. So, that's the cause of the exception.
However there some things that won't work in addPoints method:
You should check that find() method doesn't return a null object.
customer.getRewardsPoints(customer.getRewardsPoints() + amount) never sets the property (does it compile?)
EntityManager.persist() throws exception if the entity already exists. You probably want to remove that line if you only want to edit (update) the entity.
Note: I am not sure that the code you have posted is really compiling and causing that exception. That's probably caused by another version.

java.rmi.UnmarshalException: error unmarshalling return; nested exception is:java.lang.ClassNotFoundException:

I have the following situation:
Using RMI, i noticed that under a specific situation, the RMI client did not have the class whose instance was sent via RMI. So, I sent the class in the shape of Byte [] and then loaded it with a class loader i defined.
The code in the client side is something like:
pp = plugins.getPanelClasses(); //RMI method
panelClassLoader pcl = new panelClassLoader(); //simple class loader defined by me
String name = pcl.defineClass(pp);
Then, i ask in the client side by the instance of the class loaded:
HashMap<String, PluginPanel> panels = null;
try
{
panels = plugins.getSettingsPanels();
} catch (RemoteException ex)
{
Logger.getLogger(ServerOptions.class.getName()).log(Level.SEVERE, null, ex);
}
PluginPanel is an interface whose implementing classes are not always in the client...
and the class loader is:
private class panelClassLoader extends ClassLoader
{
public panelClassLoader(ClassLoader parent)
{
super(parent);
}
public panelClassLoader()
{
super(getSystemClassLoader());
}
public String defineClass(byte[] b)
{
Class c = super.defineClass(null, b, 0, b.length);
resolveClass(c);
return c.getName();
}
}
Nevertheless, I'm stuck with the following error:
java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
java.lang.ClassNotFoundException: pt.ua.dicoogle.IndexPlugin.CPanel (no security manager: RMI class loader disabled)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:178)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:132)
at $Proxy22.getSettingsPanels(Unknown Source)
at pt.ua.dicoogle.rGUI.client.windows.ServerOptions.(ServerOptions.java:176)
Caused by: java.lang.ClassNotFoundException: pt.ua.dicoogle.IndexPlugin.CPanel (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:375)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1574)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1495)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1731)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at java.util.HashMap.readObject(HashMap.java:1030)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:974)
at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1848)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1752)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1328)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:350)
at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRef.java:306)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:155)
Any sugestion?
You would have to call the remote method in the context of that class loader. Not a good scheme. Have a good look at the RMI codebase feature, it is designed for exactly this situation.