I wanted to make a little "log" on what the user is doing. I have different panels and all of these have Ajax functions such as "onclick", "onevent" and "onchange". What I planned was to define an Application wide ArrayList of Strings to log all the things.
I wrote following into WicketApplication.java
public class WicketApplication extends WebApplication {
private List<String> log = new ArrayList<String>();
#Override
public Class<? extends WebPage> getHomePage() {
//code
}
#Override
public void init() {
//code
}
public List<String> getLog() {
return log;
}
public void setLog(List<String> log) {
this.log = log;
}}
Then in one of my panels:
public class Foo extends Panel{
private static final long serialVersionUID = 1L;
private WicketApplication wapp = (WicketApplication) Application.get();
public Foo(String id){
super(id);
}
public void bar(){
List<String> protocol = wapp.getLog();
protocol.add(foo.getBarName() + " has been added to " + selectedKontakt.getObject().getName());
wapp.setLog(protocol);
}
}
In a next panel I tried to create a new reference to WicketApplication. But it seems not to be the same.
Now I have these questions:
Isn't WicketApplication unique and therefore usable for this kind of manipulation?
Do I have to take a session for this?
Can I even parse Applcation to WebApplication? Because I have this error in the console
wapp <----- field that is causing the problem
Is there any other way to create an Application wide variable?
I think you are doing it wrong (on multiple levels).
Firstly: if you want to log, use a Logging framework. E.g. LogBack, preferably accessed through SLF4J
Secondly: if you don't want to use a log framework, create a log service (a dedicated object, not the Wicket Application), use Dependency Injection to inject the log service into all components where you need it. Wicket Supports both Spring and Guice
Third: Static access to the WebApplication as suggested by the accepted answer sounds like a very bad idea (but it is apparently suggested by Wicket, to be fair).
Normal way of use is (static) method. Its typical, don't be afraid.
MyApllication m = MyApllication.get();
So is genrally easy in every wicket object.
Usually "statically overrided" to return correct type, (and can give additional control).
public static MyApllication getMyApplication() {
return (MyApllication) get();
}
or
public static MyApllication get() {
return (MyApllication ) WebApplication.get();
}
When this static method returns correct type, Your problem is resolved.
Analyse how is build AuthenticatedWebApplication over WebApplication (or WebApplication over Application) , its from Wicket team and seems be canonical
BTW I You will have idea access / execute actions dependent on user / session similar idea exist : WebSession override in MySession
Related
Using Play Framework 1.2.7, I have a class that extends play.jobs.Job that performs database writes (MongoDB using Play Moprhia plugin)
Here's an abbreviated example:
/* controller */
public static void doThings(#Required String id) {
User me = User.findById(id);
notFoundIfNull(me);
new MyJob(me).now();
}
/* MyJob */
public class MyJob extends Job {
private final User me;
public MyJob(User me) {
this.me = me;
}
#Override
public void doJob() {
int newValue = me.someInt;
newValue++;
me.someInt = newValue;
me.save();
}
}
Here's the weird part (weird to me anyway):
The write in the doJob() method does happen the first time the job is executed, sometimes a second time, but any additional instantiations of this job the write never occurs. No exceptions are thrown.
If i just remove the extends Job from MyJob and then just call the MyJob class by instantiating it myself and calling doJob() it works every time:
/* controller */
public static void doThings(#Required String id) {
User me = User.findById(id);
notFoundIfNull(me);
new MyJob(me).doJob(); // assumes this class no longer Extends Job
}
I've been using Play now for 4+ years and have never seen this kind of behavior, and i'm at a loss as to what actually is happening.
I'm not sure, but I think could be a (not handled) conflict on Morphia plugin and special on Context.
I'm sure there is something very similar in JPA model for Play1, where there is two contexts.
From your code I notice the object is loaded by Controller Context, and saved in Job Context.
When you do without job, Morphia still use the Controller one.
Try to pass only id and reload inside Job, or try to use JPDA remote debug, trap every call (inside controller and job), go deep inside Play framework and compare context object.
Good luck
I am trying to define a static method in the service interface to make an rpc call. But it doesn't allow me to do so. here I am pasting my code
Client class
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics) {
String url = GWT.getModuleBaseURL() + "domesticservice";
domesticServiceAsync = (DomesticServiceAsync) GWT.create(DomesticService.class);
ServiceDefTarget endpoint = (ServiceDefTarget) domesticServiceAsync;
endpoint.setServiceEntryPoint(url);
domesticServiceAsync.sendDomesticData(product,dma,yrmnths,dist,metrics,new Domestichandler<Void>() );
}
public class Domestichandler<Void> implements AsyncCallback<Void> {
#Override
public void onFailure(Throwable caught) {
String error = caught.getMessage();
System.out.println(error);
}
public void onSuccess(Void result) {
System.out.println("perfect");
}
}
Service
public interface DomesticService extends RemoteService {
public void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics);
}
public interface DomesticServiceAsync {
void sendDomesticData(String product,String dma,String yrmnths,String dist,String metrics,AsyncCallback<Void> callback);
}
Server side -
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics) {
System.out.println(product);
}
Basically I am trying to send the values from the front interface to the server side and I don't want any return value. But the values passed to the server side should be stored globally in the server class so i can access those values in different method. I tried changing all the senddomestic values to static but it won't allow me to do so? why?
Because RemoteServiceServlet needs to invoke your service methods somehow and the implementation expects instance methods. But this shouldn't prevent you from assigning the method data to static fields. Just be aware of multi threading.
GWT always uses instance methods for RPC calls, static methods are not possible in this case.
What is important to understand about GWT is that any RemoteServiceServlet instances are created and maintained by the servlet container (e.g. Tomcat). The servlet container might create a number of servlet instances on startup (Tomcat creates 6 RemoteServiceServlet instances by default) and then uses load balancing to determine which servlet handles an RPC request at a particular point in time. Depending on settings of course, you have little control over which RemoteServiceServlet instance exactly will handle a specific RPC request.
Therefore, if you want to store information on the server side globally using RPC calls, the idea proposed by YuPPie to use static fields of your RemoteServiceServlet implementation is a BAD idea. You will have no idea which of the RemoteServiceServlet instances maintained by the server contains your static data, and any subsequent calls to retrieve the data will give erratic results.
You have a few options, though. Storing the information in a database (or something similar) is the most straightforward option, but from your post I'm guessing you want something simpler. A singleton class which holds your data is probably the way to go. A thread-safe example:
public class DataContainer
{
private static DataContainer _singleton;
private String _dataField1;
public static synchronized DataContainer getInstance()
{
if (_singleton == null)
_singleton = new DataContainer();
return _singleton;
}
public synchronized String getDataField1()
{
return _dataField1;
}
public synchronized void setDataField1(String dataField1)
{
_dataField1 = dataField1;
}
}
Then in the server side implementation of your RPC call you could do something like:
public void sendDomesticData(String product, String dma, String yrmnths, String dist, String metrics)
{
DataContainer.getInstance().setDataField1(product);
}
This way, if there are multiple servlet instances they will all share the singleton instance of DataContainer, thus giving you a place to store your data globally. I hope this will help you.
This is my app's composition root:
MutablePicoContainer container = new DefaultPicoContainer();
container.addComponent(LDAPManager.class);
container.addComponent(LoginDelayer.class);
container.addComponent(CommandFactory.class);
container.addComponent(FileSystem.class);
container.addComponent(ProtocolFactory.class);
container.addComponent(new TemporaryFolder(container.getComponent(FileSystem.class), new File("abc")));
container.addComponent(ConnectedClientFactory.class);
container.addComponent(Server.class);
Server server = container.getComponent(Server.class);
This is cute and dandy, but there still a problem: when system-testing, I'll generally want to either mock or pass a different implementation of just one or two of those dependencies. It'd be ideal if I could just have the code shown above plus
container.addComponent(new TemporaryFolder(container.getComponent(FileSystem.class), new File("def")));
and have the container understand that I want to replace the initial TemporaryFolder instance with this new one. Is there any built-in facility for this in pico-container (or other Java lightweight containers)? If not, what's the standard approach to solve this issue?
Thanks
It might be IoC framework specific but we do this in Windsor with .net for our Acceptance Testing. Each of our services wire up there own container with all the components that they need.
In our acceptance tests we inherit from out service and call it TestXyzService and in there override any of the components that need to be overridden but leave the rest alone. This way we are testing as much as we can without making things too hard on ourselves.
In our case we have to make sure that we register the mocked or dummy component before the real one is registered in the base class as the first component takes presidence in Windsor.
Based on Bronumski answer, I've made a simple hackclass that seems to be working for my purposes atm:
import org.picocontainer.DefaultPicoContainer;
import org.picocontainer.MutablePicoContainer;
import org.picocontainer.injectors.AbstractInjector.UnsatisfiableDependenciesException;
public class IoCContainer {
private final MutablePicoContainer container = new DefaultPicoContainer();
public void addComponent(Object component) {
if (containsComponent(component.getClass()))
container.removeComponent(component.getClass());
container.addComponent(component.getClass(), component);
}
public void addComponent(Class<?> key, Object component) {
if (containsComponent(key))
container.removeComponent(key);
container.addComponent(key, component);
}
public void addComponent(Class<?> key, Class<?> component) {
if (containsComponent(key))
container.removeComponent(key);
container.addComponent(key, component);
}
public void addComponent(Class<?> component) {
if (containsComponent(component))
container.removeComponent(component);
container.addComponent(component);
}
public boolean containsComponent(Class<?> component) {
try {
container.getComponent(component);
} catch (UnsatisfiableDependenciesException e) {
return false;
}
return true;
}
public <T> T getComponent(Class<T> component) {
T result = container.getComponent(component);
if (result == null)
throw new NoComponentFoundException();
return result;
}
}
Actually, this is very easy. Note this caveat from the Javadoc for addComponent(java.lang.Object)
Register an arbitrary object. The class of the object will be used as
a key. Calling this method is equivalent to calling
addComponent(componentImplementation, componentImplementation).
(Emphasis mine.)
You can also set the key explicitly by using addComponent(java.lang.Object, java.lang.Object, org.picocontainer.Parameter...), if you desire.
Based upon additional information, this behavior will cause a key collision when two members of the same class are specified to the former interface. To fix this, you'll need some method to reconcile the conflict... which you've gone ahead and provided a working code example for here.
I openly admit that I don't use this framework for dependency injection, so if I'm off-base here, my apologies. I do highly recommend giving Mockito a try sometime, though. It's an absolute pleasure to use for these scenarios.
You could use one of the disambiguation techniques to make you test component more specific than your normal real component, so that your test one overrides it.
e.g.
public class Service {
private String data;
public Service(String data) {
this.data = data;
}
public String getData() {
return data;
}
public static void main(String[] args) {
MutablePicoContainer container = new DefaultPicoContainer();
container.as(Characteristics.USE_NAMES).addComponent(Service.class);
container.addComponent("Real Data");
// below line added only in test for injecting test data ...
container.addComponent("data", "Mock Data");
System.out.println(container.getComponent(Service.class).getData());
}
}
and this prints Mock Data if the "Mock Data" line is present, and Real Data if its commented out. This works because 'data' is the parameter name.
I have a project on Eclipse, Wicket, Spring, Hibernate. Every thing works normaly except : when I try
public class SortableContactDataProvider extends SortableDataProvider<User>
{
#SpringBean
private Service service;
public Iterator<User> iterator(int first, int count)
{
//SortParam sp = getSort();
return service.findAllUsers().subList(0, 15).iterator();
}
...
the service variable is null? In any another places when I use this constuction "service" is not null and working well. Please help me to solve this problem.
#SpringBean works only in any Subclass of Component.
You need to do the following in your Constructor
Wicket 1.4
InjectorHolder.getInjector().inject(this);
Wicket 1.5+
org.apache.wicket.injection.Injector.get().inject(this);
See 'generic IDataProvider implementation' # http://stronglytypedblog.blogspot.com/2009/03/wicket-patterns-and-pitfalls-1.html
Enjoy
A bit more of context for those who are newbies to Wicket/Spring environment - as bert, pointed out, #SpringBean works only in any Subclass of Component so you'll need to drive the injection manually. This is a 2 step process:
Drive the injection in your class, something as:
public class SortableContactDataProvider extends SortableDataProvider<User>
{
#SpringBean
private Service service;
public SortableContactDataProvider(){
Injector.get().inject(this); // set up the injection
}
public Iterator<User> iterator(int first, int count)
{
return service.findAllUsers().subList(0, 15).iterator();
}
}
And make sure the Injector is set up in Wicket application - something like:
public WicketApplication
#Override
protected void init() {
// make sure Spring injector is available and set up
getComponentInstantiationListeners().add(new SpringComponentInjector(this));
}
}
Rational
I would like to have more detailed logging debugging/logging output on a few superclasses, so the subclass name will not actually be effecting real-time performance nor application logic. I'm also of the opinion that it is fairly bad design to do this normally, however I really do want this info to be logged during development runs.
Question
Suppose I have a simple class structure as below, how do I pull the name of the subclass into the superclass without having to explicitly pass a reference?
public abstract AbstractClass {
private Logger logger = LoggerFactory.getLogger(getClass());
public AbstractClass() {}
public void execute(ContextObject context) {
if (logger.debuggingEnabled()) {
String invokingClassName = ""; // <-- how do I get this?
logger.debug("Executing {}", invokingClassName);
}
// shared application logic is here...
}
}
public MyClass extends AbstractClass {
public MyClass() {}
#Override
public void execute(ContextObject context) {
super.execute(context);
// application logic...
}
}
I have worked with parsing stack traces before and I suspect that is the route I will have to go if I want this information. Does anyone know of a library that will do this for me or a good code snippet?
Doesn't this.getClass().getName() do the trick? Namely:
public void execute(ContextObject context) {
if (logger.debuggingEnabled()) {
String invokingClassName = ""; // <-- how do I get this?
logger.debug("Executing {}", this.getClass().getName());
}
// shared application logic is here...
}
You've already got that information when you execute this line:
private Logger logger = LoggerFactory.getLogger(getClass());
That means you'll be logging with a category for the actual class. As that information is in the log already, I don't think it makes much sense to also include it in the execute method. Just make sure that your log output format includes the category name and it should be fine.
Why do you want to log the class name explicitly. Log4j already do that. The way you have defined your Logger will do the trick. Check your log file.