Serialization with runtime class loaders

I have a problem with the java serialization.
This is the environment:

- The A program that loads a set of classes (using Class.forName command with custom classloader) and creates new instances for those classes.
All instances will be saved into List<Object> and sended through socket with writeObject method.

- The B program that loads the same set of classes (always in runtime mode, with Class.forName command) and receives the List<Object> from socket with readObject command.

So, the problem is that i receive an exception(ClassNotFoundException) during the readObject method execution. I suppose that when I load all classes at startup, my principal classloader don't uses the new classes (that have their own classloaders).

But, how can i read runtime loaded objects from readObject? How can i tell to readObject to use my additional classloaders?

thanks

Comments

  • Um, could you post a bit of code?

    But here's a link, maybe that will help you ^^.

    http://www.tutorialspoint.com/java/java_serialization.htm
  • A Program:
    
    //CALL THIS IN CONSTRUCTOR
    private static boolean loadDatabaseLibs(String val) {
    	try {
    		File file = new File(val);
    		URLClassLoader child = 
    				new URLClassLoader((URL[]) Arrays.asList(file.toURI().toURL()).toArray());
    		classLoaders.add(child);
    		
    		return true;
    	} catch(Exception e) {
    		log.error("Unable to load database library" +
    				". Error " + e.getMessage());
    		return false;
    	}
    }
    
    public Class<?> loadTableClass(String tablename) {
    	String ns = classNamespaces.get(tablename);
    	
    	if(ns != null) {
    		for(URLClassLoader loader: classLoaders) {
    			try {
    				return Class.forName(ns, true, loader);
    			} catch(Exception e) {
    			}
    		}
    	}
    	
    	return null;
    }
    
    
    private List<Object> createRequestedDatabaseForTable(ResultSet resultset) throws Exception {
    	try {
    		String tablename = resultset.getMetaData().getTableName(1);
    		Class<?> objectcl = null;
    
    		objectcl = loadTableClass(tablename);
    		
    		int columns = resultset.getMetaData().getColumnCount();
    		List<Object> result = new ArrayList<Object>();
    		
    		while(resultset.next()) {
    			Object objectin = objectcl.newInstance();	
    			
    			for(int i = 1; i <= columns; i++) {
    				Field fld = objectcl.getField(resultset.getMetaData().getColumnName(i));
    				fld.set(objectin, resultset.getObject(i));
    			}
    			result.add(objectin);
    		}
    		
    		resultset.close();
    		return result;
    		
    	} catch (SQLException | InstantiationException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
    		throw new Exception(e);
    	}
    }
    
    


    and B Program
    //CALL THIS IN CONSTRUCTOR
    private static boolean loadDatabaseLibs(String val) {
    	try {
    		File file = new File(val);
    		URLClassLoader child = 
    				new URLClassLoader((URL[]) Arrays.asList(file.toURI().toURL()).toArray());
    		classLoaders.add(child);
    		
    		return true;
    	} catch(Exception e) {
    		log.error("Unable to load database library" +
    				". Error " + e.getMessage());
    		return false;
    	}
    }
    
    //CALL THIS IN CONSTRUCTOR
    public Class<?> loadTableClass(String tablename) {
    	String ns = classNamespaces.get(tablename);
    	
    	if(ns != null) {
    		for(URLClassLoader loader: classLoaders) {
    			try {
    				return Class.forName(ns, true, loader);
    			} catch(Exception e) {
    			}
    		}
    	}
    	
    	return null;
    }
    
    public void getDatabase() throws RTDBConnectionFailedException, RTDBLoadDBException, RTDBInvalidIndexCreationException {
    	
    	try {
    		@SuppressWarnings("unchecked")
    		List<Object> records = (List<Object>)reader.readObject();  //HERE CLASSNOTFOUND EXCEPTION
    		
    		if(records != null) {
    			log.info("Got database values with size: " + records.size());
    			
    			for(Object read: records){
    				insertNewRecord(read);
    			}
    			
    		} else {
    			log.error("Wrong number of database records founded");
    		}
    		
    		
    	} catch (IOException e) {
    		throw new RTDBConnectionFailedException(e);
    		
    	} catch (ClassNotFoundException e) {
    		e.printStackTrace();
    		throw new RTDBLoadDBException(e);
    		
    	} catch (IllegalArgumentException e1) {
    		throw new RTDBLoadDBException(e1);
    		
    	} catch (IllegalAccessException e1) {
    		throw new RTDBLoadDBException(e1);
    		
    	} catch (NoSuchFieldException e1) {
    		throw new RTDBLoadDBException(e1);
    		
    	} catch (SecurityException e1) {
    		throw new RTDBLoadDBException(e1);
    		
    	} finally {
    		closeOnlyComm();
    	}
    }
    
  • I'm not an expert, but I think this:
    for(int i = 1; i <= columns; i++) {
    				Field fld = objectcl.getField(resultset.getMetaData().getColumnName([B]i[/B]));
    				fld.set(objectin, resultset.getObject([B]i[/B]));
    }
    

    Should be like this: (Not sure)
    for(int i = 1; i <= columns; i++) {
    				Field fld = objectcl.getField(resultset.getMetaData().getColumnName([B][i][/B]));
    				fld.set(objectin, resultset.getObject([B][i][/B]));
    }
    

    I'm sorry that I can't be very helpful :idea:
  • Sorry, but:

    1) The error is a ClassNotFoundException. What to do with that code that you commented?
    2) Your code is senseless for java...
  • mykhayl wrote:
    Sorry, but:

    1) The error is a ClassNotFoundException. What to do with that code that you commented?
    2) Your code is senseless for java...

    Yeah I'm sorry, I was a bit confused that day.

    I think an object cannot be created, so it throws the exception. Hmm..

    Did you try to post this on daniweb?
Sign In or Register to comment.