Uso l'agente Freemarker e DCEVM + HotSwapManager. Questo in pratica mi permette di classificare hotswap anche quando aggiungi/rimuovi metodi.Freemarker removeIntrospectionInfo non funziona con DCEVM dopo il modello hotswap
Tutto funziona come fascino finché Freemarker utilizza la classe hotswapped come modello. Viene lanciata freemarker.ext.beans.InvalidPropertyException: Nessuna proprietà bean di questo tipo su di me anche se la reflection mostra che il metodo è presente (controllato durante la sessione di debug).
Sto usando
final Method clearInfoMethod = beanWrapper.getClass().getDeclaredMethod("removeIntrospectionInfo", Class.class);
clearInfoMethod.setAccessible(true);
clearInfoMethod.invoke(clazz);
per cancellare la cache, ma non funziona. Ho anche provato ad ottenere il campo membro classCache e cancellarlo usando il reflection ma non funziona troppo.
Cosa sto sbagliando? Ho solo bisogno di forzare il freemarker per eliminare qualsiasi introspezione sulle classi/classi di modelli che ha già ottenuto.
C'è qualche modo?
UPDATE
codice Esempio
Application.java
// Application.java
public class Application
{
public static final String TEMPLATE_PATH = "TemplatePath";
public static final String DEFAULT_TEMPLATE_PATH = "./";
private static Application INSTANCE;
private Configuration freemarkerConfiguration;
private BeansWrapper beanWrapper;
public static void main(String[] args)
{
final Application application = new Application();
INSTANCE = application;
try
{
application.run(args);
}
catch (InterruptedException e)
{
System.out.println("Exiting");
}
catch (IOException e)
{
System.out.println("IO Error");
e.printStackTrace();
}
}
public Configuration getFreemarkerConfiguration()
{
return freemarkerConfiguration;
}
public static Application getInstance()
{
return INSTANCE;
}
private void run(String[] args) throws InterruptedException, IOException
{
final String templatePath = System.getProperty(TEMPLATE_PATH) != null
? System.getProperty(TEMPLATE_PATH)
: DEFAULT_TEMPLATE_PATH;
final Configuration configuration = new Configuration();
freemarkerConfiguration = configuration;
beanWrapper = new BeansWrapper();
beanWrapper.setUseCache(false);
configuration.setObjectWrapper(beanWrapper);
try
{
final File templateDir = new File(templatePath);
configuration.setTemplateLoader(new FileTemplateLoader(templateDir));
}
catch (IOException e)
{
throw new RuntimeException(e);
}
final RunnerImpl runner = new RunnerImpl();
try
{
runner.run(args);
}
catch (RuntimeException e)
{
e.printStackTrace();
}
}
public BeansWrapper getBeanWrapper()
{
return beanWrapper;
}
}
RunnerImpl.java
// RunnerImpl.java
public class RunnerImpl implements Runner
{
@Override
public void run(String[] args) throws InterruptedException
{
long counter = 0;
while(true)
{
++counter;
System.out.printf("Run %d\n", counter);
// Application.getInstance().getFreemarkerConfiguration().setObjectWrapper(new BeansWrapper());
Application.getInstance().getBeanWrapper().clearClassIntrospecitonCache();
final Worker worker = new Worker();
worker.doWork();
Thread.sleep(1000);
}
}
Worker.java
// Worker.java
public class Worker
{
void doWork()
{
final Application application = Application.getInstance();
final Configuration freemarkerConfiguration = application.getFreemarkerConfiguration();
try
{
final Template template = freemarkerConfiguration.getTemplate("test.ftl");
final Model model = new Model();
final PrintWriter printWriter = new PrintWriter(System.out);
printObjectInto(model);
System.out.println("-----TEMPLATE MACRO PROCESSING-----");
template.process(model, printWriter);
System.out.println();
System.out.println("-----END OF PROCESSING------");
System.out.println();
}
catch (IOException e)
{
e.printStackTrace();
}
catch (TemplateException e)
{
e.printStackTrace();
}
}
private void printObjectInto(Object o)
{
final Class<?> aClass = o.getClass();
final Method[] methods = aClass.getDeclaredMethods();
for (final Method method : methods)
{
System.out.println(String.format("Method name: %s, public: %s", method.getName(), Modifier.isPublic(method.getModifiers())));
}
}
}
Model.java
// Model.java
public class Model
{
public String getMessage()
{
return "Hello";
}
public String getAnotherMessage()
{
return "Hello World!";
}
}
Questo esempio non funziona affatto. Anche la modifica di BeansWrapper durante il runtime non avrà alcun effetto.
Supponendo che chiami il metodo su 'BeansWrapper' che è effettivamente in uso, dovrebbe funzionare. Ma 'removeFromClassIntrospectionCache (Class clazz)' è un metodo pubblico, perché lo chiami così? Se si tratta di un vecchio FreeMarker, provare prima un aggiornamento. – ddekany
@ddekany: Sto affrontando lo stesso problema di Martin. Sto usando la versione 2.3.19 quindi l'aggiornamento dovrebbe fare il trucco. Comunque il commento Javadoc per il 'removeFromClassIntrospectionCache' mi fa un puzzle:" '... Se la classe verrà ancora utilizzata, la voce della cache verrà ricreata in silenzio" "- ciò significa che quando una cache del modello contiene il mapping per la classe in questione l'introspezione non otterrebbe la versione ricaricata di esso? Grazie! – plesatejvlk
Sto pulendo l'unico BeansWrapper che ho impostato sull'oggetto configurazione freemarker. Si prega di consultare un aggiornamento con l'esempio. –