How to override protected methods of a class of MVCResourceCommand in liferay? - liferay

I want to override a protected method in the class ExportArticleMVCResourceCommand which extends theBaseMVCResourceCommand class.
I want to convert journal article's to pdf in liferay 7 . I have written this functionality in its own method and wish to call that method in the doServeResource(...) method. But as doServeResource() is protected, I am not able to call it on a button submit. Therefore, I want to ask how to override this doServeResource() method in liferay 7.

Dissecting the problem
Liferay 7 is an open source Java platform an as such the best way to troubleshoot (absent any documentation) is to first at the code. You will notice that theExportArticleMVCResourceCommand class extends BaseMVCResourceCommand. In the ExportArticleMVCResourceCommand class you can see that the doServeResource method overrides it's parent's doServeResource method. In BaseMVCResourceCommand there are several things to note.
It is an abstract class
There is protected abstract void doServeResource method with no implementation.
The serveResource method simply calls the doServeResource
Piecing it together
So you want to override the doServeResource method in the ExportArticleMVCResourceCommandclass because that method does not work when the "targeted extension" is of type PDF (purportedly). You cannot override the doServeResource by extending or implementing any *MVCResourceCommand class or interface because it's either protected (and your OSGi component override is bundled separately) or in the case of MVCResourceCommand interface it doesn't exist.
Solution
Remember the doServeResource method is simply called by the serveResource method in ExportArticleMVCResourceCommand, and the serveResource method is public in both the MVCResourceCommand interface and BaseMVCResourceCommand class. Therefore to override the doServeResource method you simply need to create your own OSGi component with that appropriate annotations, have it override the serveResource method, and do not the referened serveResource method at the end of your own.
#Component(
property = {
"javax.portlet.name=" + JournalPortletKeys.JOURNAL,
"mvc.command.name=exportArticle"
},
service = MVCResourceCommand.class
public class CustomExportArticleMVCResourceCommand implements MVCResourceCommand {
#Override
public boolean serveResource
(ResourceRequest resourceRequest, ResourceResponse resourceResponse) {
// Call your custom method here
// ExportArticleUtil.sendFile("pdf", resourceRequest, resourceResponse);
}
#Reference(target = "(component.name=com.liferay.journal.web.internal.portlet.action.ExportArticleMVCResourceCommand)")
protected MVCResourceCommand mvcResourceCommand;
}

Related

How to access external class within a class in groovy

I'm new to groovy...
I've made a class. Within this class, I'd like to call an external method : LOG.error, but somehow, groovy is complaining about the method not being part of the class... how should I call that external method ?
class GAPI{
private myvar
public getResult(){
this.myvar="blabla"
LOG.error("test")
}
}
Groovy provides #Slf4j annotation that can add log field to your class, e.g.
#Slf4j
class GAPI{
private myvar
public getResult(){
this.myvar="blabla"
log.error("test")
}
}
Alternatively you can use #Log annotation that adds log field that uses java.util.logging.Logger instead of one provided with Slf4j. However in this case you have to be aware that java.util.logging.Logger uses different API, so there is no log.error() method.
In your example Groovy throws MissingPropertyException, because LOG is not defined in your class. If there is a class LOG with static method error you will have to import this class. But most probably you should just create LOG field (with annotation or manually) and call it to be most explicit (otherwise your code gets unreadable).

Abstract Class Error in Java

I'm new to Java and I'm running into a compile error I cannot figure out.
Chapter5Debug is not abstract and does not override abstract method itemStateChanged(java.awt.event.ItemEvent) in java.awt.event.ItemListener
public class Chapter5Debug extends Frame implements ItemListener
^
Can anyone help me understand what I need to do to fix this?
Appreciate the help!
Sheila
You have to remember that if ItemListener is abstract, then you will need to implement all the methods inside ItemListener. If you want to keep your current structure, you can just add an empty itemStateChanged method to your Chapter5Debug class.
To elaborate on #kevolution's answer:
public class Chapter5Debug extends Frame implements ItemListener {
public void itemStateChanged(ItemEvent e) {
// Write your method here
}
}
An abstract class is one which is just like a regular class but can contain some 'stub' - or abstract - methods. These are methods which need to be implemented by the class extending the abstract class. In this case, itemStateChanged() is marked as abstract, meaning that you need to declare it.
Abstract classes are useful for when you're writing code which you need the caller to provide guts in some ways. In this case, Java cannot know what to do when the item's state changes, but it can do a whole lot of other stuff. The other stuff is in regular methods in the Frame class, and these call the itemStateChanged() method - which will then invoke your own handling code.
You need o implement itemStateChanged(ItemEvent) within Chapter5Debug
example code
public class Chapter5Debug extends Frame implements ItemListener{
//where initialization occurs
checkbox.addItemListener(this);
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
...
} else {
label.setVisible(false);
}
}
}
ItemListener is an interface and hence implementing ItemListener means you either you will have to provide the implementation in Chapter5Debug
or
You can make Chapter5Debug abstract and then provide the implementation in the class inheriting Chapter5Debug.
Crux is that if you implementing an interface, You can't get away by not providing the implementation. Either you have to provide it there itself or carry it to the child classes.

How do I make a public view model base with WinRT classes?

I wanted to create an abstract base class for all of my view models, but I'm running into accessibility issues and can't seem to navigate through the errors. Here's an example of my code:
public ref class ViewModelBase {
...
}
public ref class OtherViewModel : ViewModelBase {
...
}
When I define my code as state above, I get the following error:
error C4585: 'MyNamespace::ViewModelBase' : A WinRT 'public ref class' must either be sealed or derive from an existing unsealed class
If, instead, I make ViewModelBase private, I get this error:
error C3213: base class 'MyNamespace::ViewModelBase' is less accessible than 'OtherViewModel'
This seems like it should be incredibly simple. What am I doing wrong?
What you are attempting is not strictly possible in C++/CX, as in VS 2012 C++/CX does not support public class inheritance for general-purpose scenarios. It is only supported enough to have the XAML scenarios work; the only possible public unsealed types are those found under the Windows::UI::Xaml namespace, and users are not able to author their own public unsealed types.
If you want to have a base class for all your view models, your only options to make all your classes private or to inherit from a base class from Windows::UI::Xaml (such as DependencyObject).
Each of these approaches has drawbacks:
using DependencyObject as your base makes all your viewmodels STA objects (so they can only be manipulated from the UI thread) in addition to having a lot of overhead that isn't really necessary.
Making your classes private means you cannot use the [Bindable] attribute to do databinding, so you would need to have a private databinding implementation. (Your private class would need to implement ICustomPropertyProvider and related interfaces.)
The "sealed" keyword means that the class cannot be inherited from. Your implementation should look something like this:
ref class ViewModelBase sealed
If you want to inherit from ViewModelBase then you need to have only the subclasses be ref classes like this:
class ViewModelBase
...
public ref class OtherViewModel sealed : ViewModelBase

How to use Rhino.Mocks to evaluate class Properties (getters and setters)

I'm studying how Rhino.Mocks works and trying to understand how can I set manually a value in a class Property.
I have seen a sample in internet where you have only desired Property as argument of Expect.Call(), instead of using a method.
MockRepository mocks = new MockRepository();
Person p = mocks.StrictMock<Person>();
Expect.Call(p.FirstName).Return("John");
Person is a class such as:
public class Person
{
public string FirstName {get;set;}
}
I always receive the error:
Invalid call, the last call has been
used or no call has been made (make
sure that you are calling a virtual
(C#) / Overridable (VB) method).
Am I missing something? Is it possible to set manually class Properties and evaluate them to see if getters and setters are working fine?
As with any mocking framework, Rhino Mocks can only mock interfaces or classes that defines virtual methods and properties.
That's because when implementing a class, Rhino creates a derived class from the one you specify, replacing every virtual (or Overridable in VB) method with a stub implementation that uses an interceptor to handle the call.
When you specify a non virtual method, Rhino can't create a wrapper.
That is also true tor sealed (NonInheritable in VB) classes.
So for your class to work, you should implement the property as such:
public class Person
{
public virtual string FirstName { get; set; }
}
This way Rhino can override the poperty accordingly.

Monotouch - global variables

How can I store/access global variables within a monotouch application? I am retrieving the GPS Location (using Monotouch.CoreLocation.CLLocationManager) during the FinishedLaunching method of the AppDelegate. How do I then access that information from a property on that appdelegate (from a view, for example)? Or is there another preferred method for global data?
UPDATE:
I just want to grab the location once, at startup, then have access to that location from all my views. Here's my AppDelegate - I'd like to access the locationManager field from a view. I can certainly add a property to do so, but I guess my question is "How do I access that property from a view (or can I even, considering it's a delegate)"?
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
private CLLocationManager locationManager = new CLLocationManager();
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
locationManager.Delegate = new GpsLocationManagerDelegate();
locationManager.StartUpdatingLocation();
window.AddSubview (navController.View);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
Generally, most people will tell you to avoid global variables and instead pass what you need into the delegate. (I would agree with that sentiment).
However, you can use a singleton class, a service locator, or a static class with static fields/properties to get global variable-like behavior in C# (or any other Dotnet/Mono compatible language).
In your case, I presume you wrote the class GpsLocationManagerDelegate yourself. If so, you can change the constructor to take parameters for the necessary information (the view, a reference to the app delegate, and/or a reference to the location manager) and store it in your GpsLocationManagerDelegate instance. If you didn't write GpsLocationManagerDelegate yourself and it's not declared sealed, subclass it and create an appropriate constructor.
This example seems close to what you're after: http://www.conceptdevelopment.net/iPhone/MapKit01/Main.cs.htm
You should make locationManager a public property, then you can access it from most places in the app like so:
CLLocationManager LocationManager {get;set;}
AppDelegate delegateReference =
(AppDelegate)UIApplication.SharedApplication.Delegate;
then access the locationmanager anywhere in code via:
delegateReference.LocationManager
Generally, you should setup such things as singletons, setup within the AppDelegate.

Resources