In Sitefinity, Sitemap generates wrong URLs - sitefinity

In my sitefinity application, when I generates sitemap it gets successfully generated but site map shows dual language prefix in URLs for all nodes.
Like a generated url node in my sitemap
<url>
<loc>http://www.example.net/en/en/individual/customer-
service</loc>
<priority>1</priority>
<xhtml:link rel="alternate" hreflang="en"
ref="http://www.example.net/en/en/individual/customer-service" />
<xhtml:link rel="alternate" hreflang="ar"
ref="http://www.example.net/en/ar/individual/customer-service" />
</url>
But I expect the generated url node like this
<url>
<loc>http://www.example.net/en/individual/customer-
service</loc>
<priority>1</priority>
<xhtml:link rel="alternate" hreflang="en"
ref="http://www.example.net/en/individual/customer-service" />
<xhtml:link rel="alternate" hreflang="ar"
ref="http://www.example.net/ar/individual/customer-service" />
</url>

To summarize what was discussed in the comments:
The issue is caused by the fact that the SubFolderUrlLocalizationStrategy had the following parameter:
includeSubfoderPrefixForDefaultLanguage = True
Removing the parameter resolves the issue.
This seems to be a bug in the Sitemap module in that version of Sitefinity, as I haven't seen it in v.10.2 for instance.
One way to keep the parameter and overcome the issue is to subscribe to the ISitemapGeneratorBeforeWriting event and modify the sitemap entries before they are saved, e.g. Replace("/en/en/", "/en/")
This article shows how:
https://knowledgebase.progress.com/articles/Article/How-to-modify-the-entries-in-sitefinity-sitemap-using-SitemapGeneratorBeforeWriting-event
protected void Application_Start(object sender, EventArgs e)
{
Bootstrapper.Initialized += Bootstrapper_Initialized;
}
void Bootstrapper_Initialized(object sender, Telerik.Sitefinity.Data.ExecutedEventArgs e)
{
if (e.CommandName == "Bootstrapped")
{
EventHub.Subscribe<ISitemapGeneratorBeforeWriting>(evt => SitemapGeneratorBeforeWritingHandler(evt));
}
}
void SitemapGeneratorBeforeWritingHandler(ISitemapGeneratorBeforeWriting #event)
{
var entries = #event.Entries;
// CRUD operations over the sitemap entries goes here
}

Related

How can I log information to a dividual file by Nlog?

I am about to log information of the Spider in some IActionResult to a dividual file with the date.
For example:
C:\20210317spider.txt
C:\20210318spider.txt
C:\20210319spider.txt
I don't want to use some method such as Logger.LogInformation to log all information into a file.
How can I achieve this? Thank you.
You can use the ${shortdate} layoutrenderer inside the FileName-Layout for the NLog FileTarget:
<nlog>
<targets>
<target type="file" name="spiderFile" fileName="C:/${shortdate}spider.txt" />
</targets>
<rules>
<logger name="Spider" writeTo="spiderFile" final="true" />
</rules>
</nlog>
See also the NLog Tutorial and the list of available layoutrenders that can be used with NLog Layout.
Then you can do this with Microsoft ILoggerFactory:
public class MyClass
{
private readonly ILogger _spiderLogger;
public MyClass(ILoggerFactory loggerFactory)
{
_spiderLogger = loggerFactory.CreateLogger("Spider");
_spiderLogger.LogInformation("Hello little spider");
}
}

Apache Camel - File Transfer on Particular Route Call

I'm trying to create a webservice which, when called look into a local directory picks up files from there and upload to the ftp server.
I'm able to create a simple route which picks file from local directory and uploads to ftp server below is the code :
<route>
<from uri="file://D:\\FTPTest?noop=true&delay=2000" />
<to uri="ftp://user#host.in:21/public_html/EnterpriseProject?password=password123#"/>
<to uri="bean:myBean?method=test" />
</route>
But, I want to this file transfer to be called when a particular route is called via restlet webservice is called, I tried with the following code, but it didn't work :
<route>
<from uri="direct:fileTransferRoute" />
<to uri="file://D:\\FTPTest?noop=true&delay=2000" />
<to uri="ftp://user#host.in:21/public_html/EnterpriseProject?password=password123#"/>
</route>
The above route is called by restlet from following route :
<route>
<from
uri="restlet:http://0.0.0.0:9080/csitec/{serviceName}?restletMethod=post" />
<process ref="serviceRouteProcessor" />
<toD uri="direct:${in.header.nextRoute}" />
</route>
Here's the code of my serviceRouteProcessor :
public void process(Exchange exchange) throws Exception {
String body = exchange.getIn().getBody(String.class);
String serviceName = exchange.getIn().getHeader(Constants.SERVICE_NAME).toString();
String nextRoute = serviceName+Constants.NEXT_ROUTE_APPENDER;
exchange.getOut().setHeader(Constants.NEXT_ROUTE, nextRoute);
exchange.getOut().setBody(body);
}
Please help me and suggest the changes needs to be done to make it work like this.
You should try the pollEnrich feature of content-enricher
In the example section you can find a example regarding files.
Your route should look something like this(I work only with camel java dsl, so this a bit xml pseudo code):
<route>
<from uri="direct:fileTransferRoute" />
<pollEnrich uri="file://D:\\FTPTest?fileName=data.txt....." />
<to uri="ftp://user#host.in:21/public_html/EnterpriseProject?password=password123#"/>
</route>
Edited :
you must understand one thing first , to is producer not consumer <to uri="file://D:\\FTPTest?noop=true&delay=2000" />
What you can do is ,
#Autowired
private CamelContext context;// if you have more than one camel context use #Qualifier and wire by bean id
public void process(Exchange exchange) throws Exception {
String body = exchange.getIn().getBody(String.class);
String serviceName = exchange.getIn().getHeader(Constants.SERVICE_NAME).toString();
context.startRoute(serviceName+Constants.NEXT_ROUTE_APPENDER);// here in nextroute you must give the routeid
}
your route must look like
<route id = "<value of serviceName+Constants.NEXT_ROUTE_APPENDER>" autoStartup = "false">
<from uri="file://D:\\FTPTest..." />
<onCompletion onFailureOnly="true">
<choice>
<when>
<simple>${property.CamelBatchComplete}</simple>
<process ref="asyncSelfShutdownProcessor"/>
</when>
</choice>
</onCompletion>
<to uri="ftp://user#host.in:21..."/>
</route>
And add asyncSelfShutdownProcessor to spring context
#Component
public class AsyncSelfShutdownProcessor implements AsyncProcessor {
#Autowired
private CamelContext context
public boolean process(Exchange exchange, AsyncCallback callback){
new Thread(() -> context.stopRoute(exchange.getFromRouteId())).start();
}
}
##############################################################################
Old :
OK I understand your need as - you have a route that moves file from file system to ftp server, all you need is this route to get executed only when you trigger from a rest service. I would do it like this ,
*I will make the route autoStartup = "false" and assign as id = "fs-to-ftp" to the route
<route id = "fs-to-ftp" autoStartup = "false">
<from uri="file://D:\\FTPTest..." />
<onCompletion onFailureOnly="true">
<process ref="asyncSelfShutdownProcessor"/>
</onCompletion>
<to uri="ftp://user#host.in:21..."/>
</route>
**Add a self shutdown async process in onComplete to the route "fs-to-ftp". Async Processor
asyncSelfShutdownProcessor= AsyncProcessorConverterHelper.convert(exchange -> {
new Thread(() -> context.stopRoute("fs-to-ftp")).start();
});
***Add the camel context dependency to rest service and start the route by id in the rest service context.startRoute("fs-to-ftp")

Optional Resources in Spring.Net

How to include Spring configuration files optionally? I think about something simular to this:
<spring>
<context>
<resource uri="file:///Objects/RequiredObjects.xml" />
<resource uri="file:///Objects/OptionalObjects.xml" required="false" />
</context>
This way I could provide developers the possibility to override some configuration parts (e.g. for a local speed improvement or automatism during app startup) without affecting the app.config and the problem that a developer could checkin his modified file when it is not really his intent to change the config for all.
Not as simple as in AutoFac (because there is already a builtin way) but possible to achieve something similar with a little coding:
using System.IO;
using System.Xml;
using Spring.Core.IO;
public class OptionalFileSystemResource : FileSystemResource
{
public OptionalFileSystemResource(string uri)
: base(uri)
{
}
public override Stream InputStream
{
get
{
if (System.IO.File.Exists(this.Uri.LocalPath))
{
return base.InputStream;
}
return CreateEmptyStream();
}
}
private static Stream CreateEmptyStream()
{
var xml = new XmlDocument();
xml.LoadXml("<objects />");
var stream = new MemoryStream();
xml.Save(stream);
stream.Position = 0;
return stream;
}
}
Register a section handler:
<sectionGroup name="spring">
...
<section name="resourceHandlers" type="Spring.Context.Support.ResourceHandlersSectionHandler, Spring.Core"/>
...
</sectionGroup>
...
<spring>
<resourceHandlers>
<handler protocol="optionalfile" type="MyCoolStuff.OptionalFileSystemResource, MyCoolStuff" />
</resourceHandlers>
...
<context>
<resource uri="file://Config/MyMandatoryFile.xml" />
<resource uri="optionalfile://Config/MyOptionalFile.xml" />
...
You'll find more information about resources and resource handlers in the Spring.Net documentation.

Page 404 NoT Found Even the Tomcat is not showing any error

I am trying to run this simple example on eclipse .As i run the server it is not showing any error .But in the browser it is showing 404 error page not found. I don't understand what is the error.I have used all the Jars in my WEB-INF/Lib folder too.
THE CODE SNIPPET is below:
CLASS HELLOWORLDACTION
package com.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import com.form.HelloWorldForm;
public class HelloWorldAction extends Action{
public ActionForward execute(ActionMapping mapping,ActionForm form,
HttpServletRequest request,HttpServletResponse response) throws Exception {
HelloWorldForm helloWorldForm = (HelloWorldForm) form;
helloWorldForm.setMessage("Hello World! Struts");
return mapping.findForward("success");}
}
CLASS HelloWorldForm
package com.form;
import org.apache.struts.action.ActionForm;
public class HelloWorldForm extends ActionForm{
String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Struts-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_3.dtd">
<struts-config>
<form-beans>
<form-bean name="helloWorldForm"
type="com.form.HelloWorldForm"/>
</form-beans>
<action-mappings>
<action path="/helloWorld"
type="com.action.HelloWorldAction"
name="helloWorldForm">
<forward name="success" path="/HelloWorld.jsp"/>
</action>
</action-mappings>
</struts-config>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>Maven Struts Examples</display-name>
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>
org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>
/WEB-INF/struts-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
HelloWorld.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%#taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<h1><bean:write name="helloWorldForm" property="message" />
</h1>
</body>
</html>
It sounds like you are using the wrong url. Tomcat generally has a folder called webapps for applications that are deployed on that server. To figure out the configuration, in Eclipse, open up the Server tab, find your Tomcat server and double-click on it.
It should bring up a properties pane with two tabs at the bottom Overview and Modules. Click on Modules and you should see the path to your app. For me, it's in the form of: /webapps/<project name>
Your full url would be localhost:8080/webapps/<project name>/anystringhere.do since you map anything in your app (localhost:8080/webapps/<project name>/) that ends in .do to the action servlet.

How do you get a Struts2 value from the .properties file programatically?

Say I have a struts.properties file with a defined value uploads.directory . How can I access that value from an Actioncontext programatically?
You can use getText("some.property.name") which return you the property value
http://struts.apache.org/maven/struts2-core/apidocs/com/opensymphony/xwork2/ActionSupport.html
Create ActionSupport Object and by using getText() method of ActionSupport class.
ActionSupport actionSupport = new ActionSupport();
actionSupport.getText("foo.bar");
Create a resources folder under src.
In the struts.xml file add a constant e.g., <constant name="struts.custom.i18n.resources" value="global"></constant>
Here global is the name of properties file.
Now you will be able to use the properties in the entire application.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- constant to define result path locations to project root directory -->
<!-- constant to define global resource bundle -->
<constant name="struts.custom.i18n.resources" value="global"></constant>
<package name="user" namespace="/" extends="struts-default">
<action name="home">
<result>/home.jsp</result>
</action>
<action name="welcome" class="com.waqar.struts2.actions.WelcomeAction">
<result name="success">/welcome.jsp</result>
</action>
</package>
</struts>
The welcome.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:property value="getText('action.welcome.title')"/></title>
</head>
<body>
<s:property value="getText('action.welcome.username')"/>: <s:property value="username"/><br>
</body>
</html>
global.properties
action.welcome.username=waqar
In action class
System.out.println(getText("action.welcome.username"));
You need to put the my.properties file or my_locale.propeties file in the package that houses your action class.
You need to put the values in properties files other than struts.properties for examples ApplicationResources.properties or my.properties which needs to be in the classpath. struts.properties file is used to load struts specific properties for example struts.i18n.encoding=UTF-8 or struts.devMode = false etc.
The thing you need to do in struts.properties after you create the properties file for your customized messages is you have to add the following property in struts.properties file
struts.custom.i18n.resources=ApplicationResources
If you have more than one custom message property files then you need to add them by separating with comma for example:
struts.custom.i18n.resources=ApplicationResources,my
Then in your action classes you can access the property values by using getText('propertyName')
you can get value from message resource file like this:
public class MyAction extends ActionSupport {
public String getUserDetails() {
if("First Name".equals(getText("label.firstName"))) {
System.out.println("In if block");
}
}
}
you can also get more information, how to get values from .properties files in java class or jsp files.
for JSP:
<s:text name="label.firstName" />
and
<s:property value="getText('label.age')" />
for more information you can go through this link:
get info here