I have written custon Appendar and override Append method. I am getting LoggingEvent in that method but when I looked at LocationInformation it is empty it shows only "?" in following properties.
protected override void Append(log4net.Core.LoggingEvent loggingEvent)
{
ClassName = loggingEvent.LocationInformation.ClassName /*contains "?"*/,
MethodName = loggingEvent.LocationInformation.MethodName /*contains "?"*/,
FileName = loggingEvent.LocationInformation.FileName /*contains "?"*/,
FullInfo = loggingEvent.LocationInformation.FullInfo /*contains "?"*/,
}
What I am doing wrong ?
Thanks
Could you try adding following line in the constructor of your custome appender:
Fix = FixFlags.All;
Set the Fix Property on the LoggingEvent in the Append-Method:
protected override void Append(LoggingEvent loggingEvent)
{
loggingEvent.Fix = FixFlags.All;
var className = loggingEvent.LocationInformation.ClassName;
// ...
}
Related
I'm working on Liferay PortletMVC, I injected the protected MVCActionCommand mvcActionCommand; with the #Reference(target = "(component.name=String.Here)", unbind = "-") to do some functions stuff inside the doProcessAction() method of my MVCActionCommand component.
My question is how can I set the component.name in the target of #Reference attribute, Should I put any String or should I put a defined one ?
component.name target the MVC command class name. So you need to provide the class name including it's package name.
To inject the instance variable mvcActionCommand, you can use something like this:
#Reference(target = "(component.name=com.test.service.impl.TestServiceImp)",
unbind = "-")
public void setMvcActionCommand(MVCActionCommand mvcActionCommand) {
this.mvcActionCommand = mvcActionCommand;
}
I wrote a full example here:
JAVA:
#Component(
immediate = true,
property = {
"javax.portlet.name=YOU_COMPONENT_NAME",
"mvc.command.name=/hello"
},
service = MVCActionCommand.class
)
public class LoginTestCommand extends BaseMVCActionCommand {
protected MVCActionCommand mvcActionCommand;
#Reference(target = "(component.name=com.liferay.login.web.internal.portlet.action.LoginMVCActionCommand)",
unbind = "-")
public void setMvcActionCommand(MVCActionCommand mvcActionCommand) {
this.mvcActionCommand = mvcActionCommand;
}
#Override
protected void doProcessAction(ActionRequest actionRequest, ActionResponse actionResponse) throws Exception {
System.out.println( "Login account doProcessAction" );
mvcActionCommand.processAction(actionRequest, actionResponse);
}
}
JSP:
<portlet:actionURL var="sayHelloURL" name="/hello">
<portlet:param name="mvcActionCommand" value="/hello" />
</portlet:actionURL>
Check this example too on Github.
See this TUTORIAL for more details about Overriding MVC Commands.
I am using Liferay 6.2 and I want to modify GetPageAttachmentAction.
I want to add the following code in strutsExecute to include the title in the file name:
public ActionForward strutsExecute(
ActionMapping actionMapping, ActionForm actionForm,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
long nodeId = ParamUtil.getLong(request, "nodeId");
String title = ParamUtil.getString(request, "title");
String fileName = ParamUtil.getString(request, "fileName");
// Here my change:
int pos = fileName.indexOf(CharPool.SLASH);
if (pos >= 0) {
title = fileName.substring(0, pos);
fileName = fileName.substring(pos + 1);
}
...
If I create a hook plugin for this change by extending BaseStrutsPortletAction with a custom class then it does not provide strutsExecute() to override.
Should I go with an Ext plugin instead? If yes, then suggest me the configuration of the Ext plugin to modify GetPageAttachmentAction.
You can do either: Hook plugin or Ext plugin.
But a hook seems to make more sense here:
public class MyGetPageAttachmentAction extends BaseStrutsPortletAction {
public void processAction(
StrutsPortletAction originalStrutsPortletAction,
PortletConfig portletConfig, ActionRequest actionRequest,
ActionResponse actionResponse)
throws Exception {
String title = ParamUtil.getString(actionRequest, "title");
String fileName = ParamUtil.getString(actionRequest, "fileName");
// Your code:
int pos = fileName.indexOf(CharPool.SLASH);
if (pos >= 0) {
title = fileName.substring(0, pos);
fileName = fileName.substring(pos + 1);
}
// Wrap request to add your new parameters (the original request parameters are immutable)
DynamicActionRequest dynamicActionRequest = new DynamicActionRequest(actionRequest, true);
dynamicActionRequest.setParameter("fileName", fileName);
dynamicActionRequest.setParameter("title", title);
// And delegate to original action
originalStrutsPortletAction.processAction(portletConfig, dynamicActionRequest, actionResponse);
}
}
(From your question I guess that you already have the correct settings in liferay-hook.xml)
I'm would like to use MOXy to marshal / unmarshal object from existing classes.
I would like to know if there is a mean to generate XML binding files (cause I don't want to use annotations) from my classes.
Or do we have to do it all with our little hands :) ?
By default JAXB/MOXy doesn't require any metadata to be specified (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html). You only need to specify the metadata where you want to override the default behaviour.
I'm guessing your real question is what is the easiest way to create the MOXy external mapping document. I do the following with Eclipse, there are probably similar steps for your favourite IDE:
Get the XML Schema for MOXy's mapping document
<EclipseLink_Home>/xsds/eclipselink_oxm_2_5.xsd
Register the XML Schema with your IDE
Eclipse | Preferences | XML | XML Catalog | Add
Create and XML document in the IDE and specify the following as the root element.
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"/>
Use the auto-complete functionality offered by your IDE to construct the XML document.
Another option is to generate jaxb classes and from those read the bindings (annotations) producing an external mapping (after which you can remove the annotations). PoC code:
public class MoxyBindingGenerator {
private static final String PACKAGE = "com.company.binding.jaxbclasses";
private static ObjectFactory xmlBindingsFactory = new ObjectFactory();
public static void main(String[] args) throws Exception {
Collection<TypeInfo> typeInfos = readAnnotations();
XmlBindings xmlBindings = xmlBindingsFactory.createXmlBindings();
xmlBindings.setPackageName(PACKAGE);
JavaTypes javaTypes = xmlBindingsFactory.createXmlBindingsJavaTypes();
xmlBindings.setJavaTypes(javaTypes);
List<JavaType> javaTypesList = javaTypes.getJavaType();
XmlEnums xmlEnums = xmlBindingsFactory.createXmlBindingsXmlEnums();
xmlBindings.setXmlEnums(xmlEnums);
List<XmlEnum> xmlEnumsList = xmlEnums.getXmlEnum();
typeInfos.stream().forEach(typeInfo -> {
if (!typeInfo.isEnumerationType()) {
fillJavaTypes(javaTypesList, typeInfo);
}
else {
fillEnumTypes(xmlEnumsList, typeInfo);
}
});
saveToFile(xmlBindings);
}
private static Collection<TypeInfo> readAnnotations() throws JAXBException, Exception {
JAXBContext jaxbContext = (JAXBContext) javax.xml.bind.JAXBContext.newInstance(PACKAGE);
Object contextState = getPrivateField(jaxbContext, "contextState");
Generator generator = (Generator) getPrivateField(contextState, "generator");
AnnotationsProcessor annotationsProcessor = generator.getAnnotationsProcessor();
Collection<TypeInfo> typeInfos = annotationsProcessor.getTypeInfo().values();
return typeInfos;
}
private static void fillEnumTypes(List<XmlEnum> xmlEnumsList, TypeInfo typeInfo) {
EnumTypeInfo et = (EnumTypeInfo) typeInfo;
XmlEnum xmlEnum = xmlBindingsFactory.createXmlEnum();
xmlEnum.setJavaEnum(et.getJavaClassName());
List<String> xmlEnumNames = et.getFieldNames();
List<Object> xmlEnumValues = et.getXmlEnumValues();
for (int i = 0; i < xmlEnumNames.size(); i++) {
String xmlEnumName = xmlEnumNames.get(i);
Object xmlEnumObject = xmlEnumValues.get(i);
XmlEnumValue xmlEnumValue = xmlBindingsFactory.createXmlEnumValue();
xmlEnumValue.setJavaEnumValue(xmlEnumName);
xmlEnumValue.setValue(xmlEnumObject.toString());
xmlEnum.getXmlEnumValue().add(xmlEnumValue);
}
xmlEnumsList.add(xmlEnum);
}
private static void fillJavaTypes(List<JavaType> javaTypesList, TypeInfo typeInfo) {
JavaType javaType = xmlBindingsFactory.createJavaType();
javaType.setName(typeInfo.getJavaClassName());
fillXmlType(javaType, typeInfo);
if (typeInfo.getXmlRootElement() != null) {
XmlRootElement xmlRootElement = typeInfo.getXmlRootElement();
xmlRootElement.setNamespace(null);
javaType.setXmlRootElement(xmlRootElement);
}
JavaAttributes javaAttributes = xmlBindingsFactory.createJavaTypeJavaAttributes();
javaType.setJavaAttributes(javaAttributes);
List<JAXBElement<? extends JavaAttribute>> javaAttributeList = javaAttributes.getJavaAttribute();
typeInfo.getNonTransientPropertiesInPropOrder().stream().forEach(field -> {
fillFields(javaAttributeList, field);
});
javaTypesList.add(javaType);
}
private static void fillFields(List<JAXBElement<? extends JavaAttribute>> javaAttributeList, Property field) {
if (field.getXmlElements() != null && field.getXmlElements().getXmlElement().size() > 0) {
XmlElements xmlElements = xmlBindingsFactory.createXmlElements();
xmlElements.setJavaAttribute(field.getPropertyName());
List<XmlElement> elements = field.getXmlElements().getXmlElement();
elements.stream().forEach(e -> {
e.setDefaultValue(null);
e.setNamespace(null);
xmlElements.getXmlElement().add(e);
});
JAXBElement<XmlElements> value = xmlBindingsFactory.createXmlElements(xmlElements);
javaAttributeList.add(value);
}
else if (!field.isAttribute()) {
XmlElement value = xmlBindingsFactory.createXmlElement();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
if (field.isNillable())
value.setNillable(field.isNillable());
if (field.isRequired())
value.setRequired(field.isRequired());
javaAttributeList.add(xmlBindingsFactory.createXmlElement(value));
}
else {
XmlAttribute value = xmlBindingsFactory.createXmlAttribute();
value.setJavaAttribute(field.getPropertyName());
value.setName(field.getSchemaName().getLocalPart());
javaAttributeList.add(xmlBindingsFactory.createXmlAttribute(value));
}
}
private static void saveToFile(XmlBindings xmlBindings)
throws JAXBException, PropertyException, FileNotFoundException, IOException {
JAXBContext xmlModelJaxbContext =
(JAXBContext) javax.xml.bind.JAXBContext.newInstance("org.eclipse.persistence.jaxb.xmlmodel");
JAXBMarshaller marshaller = xmlModelJaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
FileOutputStream fos = new FileOutputStream(new File(System.getProperty("user.home"), "binding-imspoor-oxm.xml"));
marshaller.marshal(xmlBindings, fos);
fos.close();
}
private static void fillXmlType(JavaType javaType, TypeInfo typeInfo) {
XmlType orgXmlType = typeInfo.getXmlType();
if (orgXmlType != null) {
boolean add = false;
XmlType xmlType = xmlBindingsFactory.createXmlType();
if (!StringUtils.isEmpty(orgXmlType.getName())) {
xmlType.setName(orgXmlType.getName());
add = true;
}
if (orgXmlType.getPropOrder() != null && orgXmlType.getPropOrder().size() > 1) {
xmlType.getPropOrder().addAll(orgXmlType.getPropOrder());
add = true;
}
if (add)
javaType.setXmlType(xmlType);
}
}
private static Object getPrivateField(Object obj, String fieldName) throws Exception {
Field declaredField = obj.getClass().getDeclaredField(fieldName);
declaredField.setAccessible(true);
return declaredField.get(obj);
}
}
I've got this action in MVC
[OutputCache(Duration = 1200, VaryByParam = "*")]
public ActionResult FilterArea( string listType, List<int> designersID, int currPage = 1 )
{
// Code removed
}
that fails to present the correct HTML with url like
http://example.com/en-US/women/clothing?designersID=158
http://example.com/en-US/women/clothing?designersID=158&designersID=13
Is this a know bug of OutputCache in .NET cause cannot recognize VaryByParam with a list param or am I missing something?
I too had the same issue in MVC3 and I believe it's still the same case in MVC5.
Here is the setup I had.
Request
POST, Content-Type:application/json, passing in an array of string as the parameter
{ "options": ["option1", "option2"] }
Controller Method
[OutputCache(Duration = 3600, Location = OutputCacheLocation.Any, VaryByParam = "options")]
public ActionResult GetOptionValues(List<string> options)
I tried every option possible with OutputCache and it just wasn't caching for me. Binding worked fine for the actual method to work. My biggest suspicion was that OutputCache wasn't creating unique cache keys so I even pulled its code out of System.Web.MVC.OutputCache to verify. I've verified that it properly builds unique keys even when a List<string> is passed in. Something else is buggy in there but wasn't worth spending more effort.
OutputCacheAttribute.GetUniqueIdFromActionParameters(filterContext,
OutputCacheAttribute.SplitVaryByParam(this.VaryByParam);
Workaround
I ended up creating my own OutputCache attribute following another SO post. Much easier to use and I can go enjoy the rest of the day.
Controller Method
[MyOutputCache(Duration=3600)]
public ActionResult GetOptionValues(Options options)
Custom Request class
I've inherited from List<string> so I can call the overriden .ToString() method in MyOutputcache class to give me a unique cache key string. This approach alone has resolved similar issues for others but not for me.
[DataContract(Name = "Options", Namespace = "")]
public class Options: List<string>
{
public override string ToString()
{
var optionsString= new StringBuilder();
foreach (var option in this)
{
optionsString.Append(option);
}
return optionsString.ToString();
}
}
Custom OutputCache class
public class MyOutputCache : ActionFilterAttribute
{
private string _cachedKey;
public int Duration { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.Url != null)
{
var path = filterContext.HttpContext.Request.Url.PathAndQuery;
var attributeNames = filterContext.ActionParameters["Options"] as AttributeNames;
if (attributeNames != null) _cachedKey = "MYOUTPUTCACHE:" + path + attributeNames;
}
if (filterContext.HttpContext.Cache[_cachedKey] != null)
{
filterContext.Result = (ActionResult) filterContext.HttpContext.Cache[_cachedKey];
}
else
{
base.OnActionExecuting(filterContext);
}
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
filterContext.HttpContext.Cache.Add(_cachedKey, filterContext.Result, null,
DateTime.Now.AddSeconds(Duration), System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Default, null);
base.OnActionExecuted(filterContext);
}
}
EDIT 2: If you're looking for an answer to a similar problem, check Stuart's answer and my comments on it.
EDIT: I am actually getting a Mono.Debugger.Soft.VMDisconnectedException. I also recently installed Windows 8.1 and Resharper (though Resharper is suspended now).
When I access a very simple list property of my view model in my MVVMCross Xamarin iOS application, the program fails. It doesn't quit most of the time: it acts like it's running. The simulator has a black screen and there is no exception. If I breakpoint on if (messagesViewModel != null) source.ItemsSource = messagesViewModel.Messages; and then type messagesViewModel.Messages into the Immediate Window, everything stops, so I can tell it is failing at this line. If instead I "step over", it never moves to the next line.
I was having similar behavior when I was toggling this code in the MvxTableViewSource:
public override int RowsInSection(UITableView tableview, int section)
{
return 1;
}
My view model looks like this:
public class MessagesViewModel : MvxViewModel
{
private List<BaseMessage> _messages = null;
public List<BaseMessage> Messages
{
get
{
return _messages; //yes, I know I'm returning null
//I wasn't at first.
}
}
public MessagesViewModel()
{
}
}
This is my ViewDIdLoad on the MvxTableViewController:
public override void ViewDidLoad()
{
base.ViewDidLoad();
var source = new MessagesTableViewSource(TableView);
//was binding here, removed it for debug purposes
//failure on second line here
var messagesViewModel = ViewModel as MessagesViewModel;
if (messagesViewModel != null) source.ItemsSource = messagesViewModel.Messages;
TableView.Source = source;
TableView.ReloadData();
}
Some initialization code:
public class App : MvxApplication
{
public App()
{
var appStart = new MvxAppStart<MessagesViewModel>();
Mvx.RegisterSingleton<IMvxAppStart>(appStart);
}
}
public partial class AppDelegate : MvxApplicationDelegate
{
//empty functions removed.
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var presenter = new MvxTouchViewPresenter(this, Window);
var setup = new Setup(this, presenter);
setup.Initialize();
var startup = Mvx.Resolve<IMvxAppStart>();
startup.Start();
Window.MakeKeyAndVisible();
return true;
}
}
I suspect whatever the error is, it isn't in any of the code you have posted.
I just created a simple ViewModel:
public class FirstViewModel
: MvxViewModel
{
private List<string> _items = new List<string>() { "One", "Two", "Three"};
public List<string> Items
{
get { return _items; }
set { _items = value; RaisePropertyChanged(() => Items); }
}
}
And a simple View:
[Register("FirstView")]
public class FirstView : MvxTableViewController
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
// ios7 layout
if (RespondsToSelector(new Selector("edgesForExtendedLayout")))
EdgesForExtendedLayout = UIRectEdge.None;
var firstViewModel = ViewModel as FirstViewModel;
var source = new MessagesTableViewSource(TableView);
source.ItemsSource = firstViewModel.Items;
TableView.Source = source;
}
public class MessagesTableViewSource : MvxTableViewSource
{
public MessagesTableViewSource(UITableView tableView) : base(tableView)
{
tableView.RegisterClassForCellReuse(typeof(MessagesCell), new NSString("MessagesCell"));
}
protected override UITableViewCell GetOrCreateCellFor(UITableView tableView, NSIndexPath indexPath, object item)
{
return tableView.DequeueReusableCell("MessagesCell");
}
}
public class MessagesCell : MvxTableViewCell
{
public MessagesCell(IntPtr handle)
: base(handle)
{
var txt = new UILabel(new RectangleF(0, 0, 320, 44));
Add(txt);
this.DelayBind(() =>
{
this.CreateBinding(txt).Apply();
});
}
}
}
And this code runs fine...
I wouldn't completely trust the integration of Xamarin.iOS with the Immediate window - it is better now than it used to be, but I've seen several problems with it before.
Some things to possibly check:
does the above code work for you?
if it does, then what's in your BaseMessage and MessagesTableViewSource classes - perhaps they are causing the problem?
can you use Mvx.Trace("The list is {0}", messagesViewModel.Messages ?? "-null") to view the list? Can you use trace within the ViewModel property get - is it being called? Can you use trace within the ViewModel constructor?
are all your assemblies building against the same versions of things? Are all your assemblies definitely rebuilt? (Check "Build|Configuration Manager")- what version of Xamarin.iOS are you running in VS and in the Mac?