IllegalAccessException doing Thymeleaf/OGNL method access - java

I'm new to web dev and I'm trying Thymeleaf template engine on App Engine. It has worked fine so far, except I always get java IllegalAccessException's when I attempt method (as opposed to simple attribute) access.
For example, with this line of HTML:
<div class="panel" th:id="${item.getWebId()}">
I get:
java.lang.IllegalAccessException:
Method [public java.lang.String myapp.ItemInfo.getWebId()] cannot be accessed.
at ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:851)
This happens both on dev server (Win Vista) and in production with GAE SDK's 1.9.0 and 1.8.9. I've tried the current TL (2.1.2) and the previous version (2.0.20). I'm not using Spring.
I've found others having reflection problems (here and here) on the TL forum, but nothing that helps.
Some people using Struts or Spring encountered similar problems a long time ago, and resolved them by setting OgnlRuntime.setSecurityManager(null). I haven't pursued this because I can't see how to access the OgnlRuntime object in TL, and it doesn't make much sense to me that I would be the only TL user to need this.
Looking at OgnlRuntime v3.0.6 (here) it looks like the easiest solution would be to disable 'checkPermission', but again, as someone new to TL, I'm hesitant to make a change that TL doesn't expose, and that no one else using TL seems to need to do. There must be something else wrong?

In the end I proceeded with the OgnlRuntime.setSecurityManager(null) option. It seems like a bad idea but it allows me to proceed for now.
Here's the code I used:
public class MyContextListener implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent arg0) {
}
#Override
public void contextInitialized(ServletContextEvent arg0) {
OgnlRuntime.setSecurityManager(null);
}
}
And in my web.xml I added:
<listener>
<listener-class>com.myapp.MyContextListener</listener-class>
</listener>

Related

using CayenneRuntime in webapplication without web.xml

I have a Wicket application and I'm trying to implement separate configuration that can be changed remotely. That's the end goal, anyway.
What I'm trying to do is set up Cayenne to work by starting it manually, rather than using the web.xml file. I have tried a bunch of different things, but I'm not sure I fully understand how the context is applied to all threads.
I have tried creating a ServerRuntime in my Application class. I've also tried on my custom BasePage class that each page uses. I can get it to kind of work by doing the following on the BasePage, but it is inconsistent:
public class BasePage ....
public static ServerRuntime runtime = new ServerRuntime("cayenne-config.xml");//This is in my BasePage class, but I've also tried this in the Application class
#Override
protected void init() {
BaseContext.bindThreadObjectContext(Application.runtime.getContext());//This is in my BasePage class
}
Like I said, that kind of works, but it isn't consistent. I keep getting errors on
BaseContext.getThreadObjectContext();
Error is this:
java.lang.IllegalStateException: Current thread has no bound ObjectContext.
I can't seem to find much information on this. I tried doing stuff like this, and accessing the runtime using these as well, but nothing is working consistently.
WebUtil.setCayenneRuntime(this.getServletContext(), runtime);
BaseContext.bindThreadObjectContext(WebUtil.getCayenneRuntime(((Application)getApplication()).getServletContext()).getContext());
Any help would be greatly appreciated.
I figured out a way to do this on my own.
I'm extending CayenneFilter and overriding the init method.
In there I copied nearly their exact code. I will be able to check for any config here and load the proper xml file. This obviously isn't the ironed out solution, but is definitely a step forward, and could be the way I end up doing this.
Either way, here's what I have tested to be working.
#WebFilter(filterName = "cayenne-config", displayName = "cayenne-config", urlPatterns = {"/*"})
public class TestFilter extends CayenneFilter
{
#Override
public void init(FilterConfig config) throws ServletException
{
this.checkAlreadyConfigured(config.getServletContext());
this.servletContext = config.getServletContext();
WebConfiguration configAdapter = new WebConfiguration(config);
Collection modules = configAdapter.createModules(new Module[]{new WebModule()});
ServerRuntime runtime = new ServerRuntime("cayenne-test.xml", (Module[])modules.toArray(new Module[modules.size()]));
WebUtil.setCayenneRuntime(config.getServletContext(), runtime);
}
}
I don't think the annotation is needed (I am specifying it all in the web.xml file), but I thought I would leave it here so you could see that it is changing.
If I could find a way to change the config (FilterConfig) values (the init parameters), then I could just change that to the name of the xml file I want to use and not override this entire method. I couldn't figure out how to do that, but I'll look further later.
If anyone has another better answer, I would love to hear it.

Configuring DropWizard Programmatically

I have essentially the same question as here but am hoping to get a less vague, more informative answer.
I'm looking for a way to configure DropWizard programmatically, or at the very least, to be able to tweak configs at runtime. Specifically I have a use case where I'd like to configure metrics in the YAML file to be published with a frequency of, say, 2 minutes. This would be the "normal" default. However, under certain circumstances, I may want to speed that up to, say, every 10 seconds, and then throttle it back to the normal/default.
How can I do this, and not just for the metrics.frequency property, but for any config that might be present inside the YAML config file?
Dropwizard reads the YAML config file and configures all the components only once on startup. Neither the YAML file nor the Configuration object is used ever again. That means there is no direct way to configure on run-time.
It also doesn't provide special interfaces/delegates where you can manipulate the components. However, you can access the objects of the components (usually; if not you can always send a pull request) and configure them manually as you see fit. You may need to read the source code a bit but it's usually easy to navigate.
In the case of metrics.frequency you can see that MetricsFactory class creates ScheduledReporterManager objects per metric type using the frequency setting and doesn't look like you can change them on runtime. But you can probably work around it somehow or even better, modify the code and send a Pull Request to dropwizard community.
Although this feature isn't supported out of the box by dropwizard, you're able to accomplish this fairly easy with the tools they give you. Note that the below solution definitely works on config values you've provided, but it may not work for built in configuration values.
Also note that this doesn't persist the updated config values to the config.yml. However, this would be easy enough to implement yourself simply by writing to the config file from the application. If anyone would like to write this implementation feel free to open a PR on the example project I've linked below.
Code
Start off with a minimal config:
config.yml
myConfigValue: "hello"
And it's corresponding configuration file:
ExampleConfiguration.java
public class ExampleConfiguration extends Configuration {
private String myConfigValue;
public String getMyConfigValue() {
return myConfigValue;
}
public void setMyConfigValue(String value) {
myConfigValue = value;
}
}
Then create a task which updates the config:
UpdateConfigTask.java
public class UpdateConfigTask extends Task {
ExampleConfiguration config;
public UpdateConfigTask(ExampleConfiguration config) {
super("updateconfig");
this.config = config;
}
#Override
public void execute(Map<String, List<String>> parameters, PrintWriter output) {
config.setMyConfigValue("goodbye");
}
}
Also for demonstration purposes, create a resource which allows you to get the config value:
ConfigResource.java
#Path("/config")
public class ConfigResource {
private final ExampleConfiguration config;
public ConfigResource(ExampleConfiguration config) {
this.config = config;
}
#GET
public Response handleGet() {
return Response.ok().entity(config.getMyConfigValue()).build();
}
}
Finally wire everything up in your application:
ExampleApplication.java (exerpt)
environment.jersey().register(new ConfigResource(configuration));
environment.admin().addTask(new UpdateConfigTask(configuration));
Usage
Start up the application then run:
$ curl 'http://localhost:8080/config'
hello
$ curl -X POST 'http://localhost:8081/tasks/updateconfig'
$ curl 'http://localhost:8080/config'
goodbye
How it works
This works simply by passing the same reference to the constructor of ConfigResource.java and UpdateConfigTask.java. If you aren't familiar with the concept see here:
Is Java "pass-by-reference" or "pass-by-value"?
The linked classes above are to a project I've created which demonstrates this as a complete solution. Here's a link to the project:
scottg489/dropwizard-runtime-config-example
Footnote: I haven't verified this works with the built in configuration. However, the dropwizard Configuration class which you need to extend for your own configuration does have various "setters" for internal configuration, but it may not be safe to update those outside of run().
Disclaimer: The project I've linked here was created by me.
I solved this with bytecode manipulation via Javassist
In my case, I wanted to change the "influx" reporter
and modifyInfluxDbReporterFactory should be ran BEFORE dropwizard starts
private static void modifyInfluxDbReporterFactory() throws Exception {
ClassPool cp = ClassPool.getDefault();
CtClass cc = cp.get("com.izettle.metrics.dw.InfluxDbReporterFactory"); // do NOT use InfluxDbReporterFactory.class.getName() as this will force the class into the classloader
CtMethod m = cc.getDeclaredMethod("setTags");
m.insertAfter(
"if (tags.get(\"cloud\") != null) tags.put(\"cloud_host\", tags.get(\"cloud\") + \"_\" + host);tags.put(\"app\", \"sam\");");
cc.toClass();
}

Picocontainer 2.14.3 and AOP

I'm trying to use AOP with picocontainer.
so far I found in the documentation:
http://picocontainer.codehaus.org/interception.html
pico = new DefaultPicoContainer();
pico.as(INTERCEPT).addComponent(Apple.class, BraeburnApple.class);
and then create the interceptor, but looking through the code, I cannot find the INTERCEPT property anywhere.
as receives a Properties value, which pico implements in Characteristics class.
anyone has a clue, or has implemented it before and knows how to keep with it?
Thanks
looks like the property for this Behavior is somehow missing in this pico version, check org.picocontainer.Characteristics in older versions, I really hope it was implemented somewhere :)
Also there's old styled way for interception in pico: http://www.markhneedham.com/blog/2008/11/11/logging-with-pico-container/
Since the 2.14.3 org.picocontainer.behaviors still have these classes, I suppose this way is ok
This worked for me. First, create a proxy by extending a bean:
public static class ChangeMapInfoEndpointInterceptor extends MapInfoRoutingManagementBean {
#Override
public void setEndpoint(String endpoint) {
System.out.println("setEndpoint called");
}
}
Then pass it to the intercepting-styled container:
MutablePicoContainer context = new PicoBuilder().withBehaviors(new Intercepting()).build();
context.addComponent(MapInfoRoutingManagement.class, MapInfoRoutingManagementBean.class);
Intercepted intercepted = context.getComponentAdapter(MapInfoRoutingManagement.class).findAdapterOfType(Intercepted.class);
intercepted.addPostInvocation(MapInfoRoutingManagement.class, new ChangeMapInfoEndpointInterceptor());

Eclipse e4: Accessing properties in PostContextCreate

I am using the PostContextCreate part of the life cycle in an e4 RCP application to create the back-end "business logic" part of my application. I then inject it into the context using an IEclipseContext. I now have a requirement to persist some business logic configuration options between executions of my application. I have some questions:
It looks like properties (e.g. accessible from MContext) would be really useful here, a straightforward Map<String,String> sounds ideal for my simple requirements, but how can I get them in PostContextCreate?
Will my properties persist if my application is being run with clearPersistedState set to true? (I'm guessing not).
If I turn clearPersistedState off then will it try and persist the other stuff that I injected into the context?
Or am I going about this all wrong? Any suggestions would be welcome. I may just give up and read/write my own properties file.
I think the Map returned by MApplicationElement.getPersistedState() is intended to be used for persistent data. This will be cleared by -clearPersistedState.
The PostContextCreate method of the life cycle is run quite early in the startup and not everything is available at this point. So you might have to wait for the app startup complete event (UIEvents.UILifeCycle.APP_STARTUP_COMPLETE) before accessing the persisted state data.
You can always use the traditional Platform.getStateLocation(bundle) to get a location in the workspace .metadata to store arbitrary data. This is not touched by clearPersistedState.
Update:
To subscribe to the app startup complete:
#PostContextCreate
public void postContextCreate(IEventBroker eventBroker)
{
eventBroker.subscribe(UIEvents.UILifeCycle.APP_STARTUP_COMPLETE, new AppStartupCompleteEventHandler());
}
private static final class AppStartupCompleteEventHandler implements EventHandler
{
#Override
public void handleEvent(final Event event)
{
... your code here
}
}

Creation of Stateless Components

I have created a stateless component in Wicket 1.5, by extending the component and giving the #StatelessComponent annotation,
I was trying to check the component being stateful/stateless with the StatelessChecker.
But i am not able to check, here is the code which i was trying .
#StatelessComponent
public class StatelessText extends TextField
//Client Class
StatelessText test = new StatelessText("test");
StatelessChecker sc = new StatelessChecker();
sc.onBeforeRender(test);
I dont see anything on console or any exceptions/errors.
Maybe i am not using the correct way, Can anybody please guide me here.
Appreciate the Help.
you have to register the StatelessChecker during the init of the WicketApplication.
/**
* #see org.apache.wicket.Application#init()
*/
#Override
public void init() {
super.init();
// might want to check if you're in dev mode or not...
getComponentPreOnBeforeRenderListeners().add(new StatelessChecker());
}
You dont need to explicitly call the Statelesschecker in your class. As Throsten said you need to add that in your WebApplications init and annotate your - class to be checked - as Statelesscomponent. If your Application is confidured to be in development mode in you web.xml you will get a runtime error when calling this page if it is Statefull.
Im not sure I understood what you are trying to do there. why are you holding an instance of your class in itself? are you trying to build a singleton? And what purpose does StatelessText has anyway? the Textfield in an usual form will be Stateless as long theres no explicitly added Ajax behaviour to it.

Categories

Resources