SharePoint 2010: Redeploying feature adds duplicate web parts to page - sharepoint-2010

I am provisioning a publishing page as part of a feature and placing a single list view web part on the page (see code below). This all works perfectly sp far.
<Elements>
<Module>
<File Path="default.aspx" Url="BulletinBoard.aspx" Type="GhostableInLibrary" IgnoreIfAlreadyExists="TRUE">
<Property Name="Title" Value="Bulletin Board" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/ListNewsletterStyle.aspx" />
<Property Name="ContentType" Value="Page" />
<Property Name="PublishingPageImage" Value="" />
<View List="Lists/BulletinBoard" BaseViewID="2" WebPartZoneID="Main" WebPartOrder="1">
<![CDATA[
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Microsoft.SharePoint.WebPartPages.XsltListViewWebPart,Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title">Active Announcements</property>
<property name="ChromeType">None</property>
</properties>
</data>
</webPart>
</webParts>
]]>
</View>
</File>
</Module>
</Elements>
The only problem is that each time I redeploy my feature through Visual Studio, the list view web part is duplicated (i.e. another one is added to the web part zone).
This problem only appears to affect web parts with the <View ...> tag. Web parts provisioned with the <AllUsersWebPart ...> tag are not being duplicated.
How do I prevent this?

You can add a feature receiver and add the webpart if it not alreay exists in stead of adding the webpart in XML.
What do you mean by tag?

Check out this blog entry from Waldek Mastykarz. It has the C# code below that should be similar to what you are looking for.
using (SPSite site = new SPSite("http://sharepoint"))
{
SPList list = site.GetCatalog(SPListTemplateType.MasterPageCatalog);
SPListItemCollection items = list.Items;
List<string> webParts = new List<string>();
// find the right Page Layout
foreach (SPListItem item in items)
{
if (item.Name.Equals("CustomPageLayout.aspx",
StringComparison.CurrentCultureIgnoreCase))
{
SPFile file = item.File;
// get the Web Part Manager for the Page Layout
SPLimitedWebPartManager wpm =
file.GetLimitedWebPartManager(PersonalizationScope.Shared);
// iterate through all Web Parts and remove duplicates
while (wpm.WebParts.Count > 0)
{
StringBuilder sb = new StringBuilder();
XmlWriterSettings xws = new XmlWriterSettings();
xws.OmitXmlDeclaration = true;
XmlWriter xw = XmlWriter.Create(sb, xws);
System.Web.UI.WebControls.WebParts.WebPart wp =
wpm.WebParts[0];
wpm.ExportWebPart(wp, xw);
xw.Flush();
string md5Hash = getMd5Hash(sb.ToString());
if (webParts.Contains(md5Hash))
wpm.DeleteWebPart(wp);
else
webParts.Add(md5Hash);
}
}
}
}

Note to SharePoint 2013 users. You should add ReplaceContent=True to the tag. The duplicate webpart issue will be resolved.

Related

Deploying Custom RoleMapper to WebLogic

I am trying to deploy a Custom Role Mapper in WebLogic 10.3.5.0 - this is very similar to this question - Weblogic Providers, but I cannot get the provider to appear in the poplist.
Config file:
<MBeanType Name="DatabaseRoleMapping"
DisplayName="DatabaseRoleMapping"
Package="com.bynx.weblogic.mbean.rolemapping"
Extends="weblogic.management.security.authorization.RoleMapper"
PersistPolicy = "OnUpdate">
<MBeanAttribute
Name = "ProviderClassName"
Type = "java.lang.String"
Writeable = "false"
Preprocessor = "weblogic.management.configuration.LegalHelper.checkClassName(value)"
Default = ""com.bynx.weblogic.mbean.rolemapping.DatabaseRoleMappingProvider""
/>
<MBeanAttribute
Name = "Description"
Type = "java.lang.String"
Writeable = "false"
Default = ""Provider that performs Role Mapping held in a database""
/>
<MBeanAttribute
Name = "Version"
Type = "java.lang.String"
Writeable = "false"
Default = ""1.0""
/>
<!--
<MBeanAttribute
Name = "DataSourceJNDI"
Type = "java.lang.String"
Default = ""UserDataSource""
Description = "DataSource JNDI name"
/> -->
</MBeanType>
Provider Imlementation:
package com.bynx.weblogic.mbean.rolemapping;
import weblogic.management.security.ProviderMBean;
import weblogic.security.spi.RoleMapper;
import weblogic.security.spi.RoleProvider;
import weblogic.security.spi.SecurityServices;
public class DatabaseRoleMappingProvider implements RoleProvider
{
DatabaseRoleMapper mapper;
private String description;
#Override
public String getDescription()
{
return description;
}
#Override
public void initialize(ProviderMBean provider, SecurityServices services)
{
//DatabaseRoleMappingProviderMBean mBean = (DatabaseRoleMappingProviderMBean)provider;
//mapper = new DatabaseRoleMapper(mBean.getDataSourceJNDI());
mapper = new DatabaseRoleMapper("UserDataSource");
description = provider.getName() + " " + provider.getVersion();
}
#Override
public void shutdown()
{
}
#Override
public RoleMapper getRoleMapper()
{
return mapper;
}
}
Build file:
<?xml version="1.0"?>
<project name="dbuser_authentication_provider" default="all" basedir=".">
<!-- global properties -->
<property environment="env"/>
<property name="jdk" value="C:/Program Files (x86)/Java/jdk1.6.0_26"/>
<property name="lib" value="P:/Web_Dev/Projects/WebLogic_Home/wlserver_10.3/server/lib"/>
<property name="mbeantypes" value="${lib}/mbeantypes"/>
<property name="sampleprovidersjar" value="databaseRoleMapping.jar"/>
<property name="sample_dir" location="."/>
<property name="src_dir" value="${sample_dir}/src"/>
<property name="provider_src_dir" value="${src_dir}/com"/>
<property name="build_dir" value="${sample_dir}/build"/>
<property name="class_dir" value="${sample_dir}/classes"/>
<property name="namespace" value="http://www.bea.com/ns/90/weblogic/security/samples"/>
<target name="all" depends="clean">
<!-- Set up the build directories -->
<mkdir dir="${build_dir}"/>
<mkdir dir="${class_dir}"/>
<!-- Only copy over the commo dtd and sample provider xml files for now -->
<copy todir="${build_dir}" flatten="true">
<fileset dir="${lib}">
<include name="commo.dtd"/>
</fileset>
</copy>
<copy todir="${build_dir}" flatten="true">
<fileset dir="${provider_src_dir}">
<include name="**/*.xml"/>
<include name="**/*.java"/>
</fileset>
</copy>
<!-- Build the sample security providers' jar file -->
<java classname="weblogic.management.commo.WebLogicMBeanMaker" fork="true" failonerror="true">
<jvmarg line="-cp '${jdk}/lib/tools.jar';${lib}/weblogic.jar -Dfiles=${build_dir} -DMDFDIR=${build_dir} -DMJF=${build_dir}/${sampleprovidersjar} -DtargetNameSpace=${namespace} -DpreserveStubs=true -DcreateStubs=true"/>
</java>
</target>
<target name="clean">
<delete quiet="true" dir="${build_dir}"/>
<delete quiet="true" dir="${class_dir}"/>
</target>
</project>
Everything compiles fine and there don't appear to be any missing class files in the generated jar, but putting the jar in the mbeantypes directory and restarting it doesn't appear in the list. It will eventually look at a database, but I have stripped it down to the minimum to try and get it working. Any suggestions - or where to look in the logs for any issues would be appreciated.
I've managed to get this working, so thought I would share my solution in case anyone else stumbles upon this.
First the statement in the documentation:
However, if you want WebLogic Server to look for MBean types in additional directories, use the -Dweblogic.alternateTypesDirectory= command-line flag when starting your server, where is a comma-separated list of directory names. When you use this flag, WebLogic Server will always load MBean types from WL_HOME\server\lib\mbeantypes first, then will look in the additional directories and load all valid archives present in those directories (regardless of their extension).
Doesn't appear to be correct. We are using the alternateTypesDirectory parameter and I could only get WebLogic to pickup my custom MBean if I put the jar in one of the directories in the command-line flag.
Secondly, if you have anything deployed that uses versioning (e.g. one or more of the optional deployable libraries), your custom provider must implement the weblogic.security.spi.VersionableApplicationProvider interface and haveImplements = "weblogic.management.security.ApplicationVersioner" in the MBeanType element of the definition XML.

Localized file resource not found

I have included these files in my project with Build Action set to Content:
\Resources\Myfolder\Myfiles-de-DE.zip
\Resources\Myfolder\Myfiles-en-US.zip
\Resources\Myfolder\Myfiles-sv-SV.zip
\Resources\Myfolder\Myfiles-fr-FR.zip
In my Package.appxmanifest I have tried this [when "Open With..." "XML (Text) Editor"]:
<Resources>
<!-- First = Default -->
<Resource Language="en-US" />
<Resource Language="sv-SV" />
<Resource Language="de-DE" />
<Resource Language="fr-FR" />
</Resources>
and this:
<Resources>
<Resource Language="x-generate" />
</Resources>
In code I am trying to access the file like this:
Dim ZipPath As String = "Resources\Myfolder\Myfiles-.zip"
Dim fs As System.IO.Stream = Await _
Windows.ApplicationModel.Package.Current.InstalledLocation.OpenStreamForReadAsync(ZipPath)
But I get only a FileNotFoundException! What am I doing wrong?
PS: The file loads if I change the code to this:
Dim ZipPath As String = "Resources\Myfolder\Myfiles-en-US.zip"
It isn't fully clear what you're trying to accomplish. But the code should throw that exception unless you have Resources\Myfolder\Myfiles-.zip file loaded in there by default.
I'm guessing you want to load in the specific zip file based on their prefer language, but no where in your code do attempt to get their language.
You can try to do a LocalizedStrings : How to build a localized app for Windows Phone 8
Or you can just get their prefer language and append it to the ZipPath that you have
string ZipPath = "Resources\Myfolder\Myfiles-" + culture_extention + ".zip";
where culture_extention is Windows.System.UserProfile.GlobalizationPreferences.Languages[0]

Spring Webflow - IllegalStateException when using multipart/form-data and file upload

I am trying to add file upload to my Spring Webflog form processing. As far as the form enctype is not set to multipart/form-data, form submition works just fine. But after I added enctype="multipart/form-data" to my Spring form, this Exception occurs:
java.lang.IllegalStateException: A flow execution action URL can only be obtained in a RenderRequest or a ResourceRequest
at org.springframework.webflow.context.portlet.PortletExternalContext.getFlowExecutionUrl(PortletExternalContext.java:215)
at org.springframework.webflow.engine.impl.RequestControlContextImpl.getFlowExecutionUrl(RequestControlContextImpl.java:178)
at org.springframework.webflow.mvc.view.AbstractMvcView.render(AbstractMvcView.java:189)
at org.springframework.webflow.engine.ViewState.render(ViewState.java:293)
at org.springframework.webflow.engine.ViewState.refresh(ViewState.java:242)
at org.springframework.webflow.engine.ViewState.resume(ViewState.java:220)
at org.springframework.webflow.engine.Flow.resume(Flow.java:537)
at org.springframework.webflow.engine.impl.FlowExecutionImpl.resume(FlowExecutionImpl.java:259)
at org.springframework.webflow.executor.FlowExecutorImpl.resumeExecution(FlowExecutorImpl.java:169)
at org.springframework.webflow.mvc.portlet.FlowHandlerAdapter.handleAction(FlowHandlerAdapter.java:161)
at org.springframework.web.portlet.DispatcherPortlet.doActionService(DispatcherPortlet.java:670)
at org.springframework.web.portlet.FrameworkPortlet.processRequest(FrameworkPortlet.java:520)
at org.springframework.web.portlet.FrameworkPortlet.processAction(FrameworkPortlet.java:461)
at com.liferay.portlet.FilterChainImpl.doFilter(FilterChainImpl.java:71)
I have added CommonsMultipartResolver to my spring context:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- Limit uploads to one byte smaller than the server is allowed to handle -->
<property name="maxUploadSize" value="100000" />
</bean>
and have commons-fileupload.jar in my pom.xml:
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.2</version>
</dependency>
My JSP looks like this:
<portlet:actionURL var="processFormAction" >
<portlet:param name="execution" value="${flowExecutionKey}"/>
</portlet:actionURL>
<form:form action="${processFormAction}" modelAttribute="customerModel" enctype="multipart/form-data" method="post" >
<form:input path="firstName" cssClass="input-size-1 valid-required" />
<form:input path="lastName" cssClass="input-size-1 valid-required" />
<input name="avatar" id="avatar" type="file"/>
<input type="submit" name="_eventId_submit" id="send" value="Submit"/>
</form:form>
My flow.xml definition:
<view-state id="state1" model="customerModel">
...
<transition on="submit" to="submitFormActions"/>
</view-state>
<action-state id="submitFormActions">
<evaluate expression="portletAction.processForm(customerModel, flowRequestContext)" />
<transition on="success" to="state2"/>
<transition on="error" to="state1" />
</action-state>
The model object:
public class CustomerModel implements Serializable{
private String firstName;
private String lastName;
private MutlipartFile avatar;
...
//public getters and setters
}
Any thoughts what could be wrong? As I said, without enctype="multipart/form-data" the form processing works well.
Thanks
You are using org.springframework.web.multipart.commons.CommonsMultipartResolver which is not aware about the portlet context.
You need to change CommonsMultipartResolver to:
<bean id="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!-- one of the properties available; the maximum file size in bytes -->
<property name="maxUploadSize" value="100000"/>
</bean>
Also, for this bean to be recognised by DispatcherPortlet, you need to define this bean id as mentioned above. The doc says:
Any configured PortletMultipartResolver bean must have the following id (or name): "portletMultipartResolver".
If you have defined your PortletMultipartResolver with any other name, then the DispatcherPortlet will not
find your PortletMultipartResolver, and consequently no multipart support will be in effect.

URIs when using domain.xml at embedded glassfish

I'm embedding a Java EE 5 application using GlassFish 3.0.1. I already can deploy it (when using without specific configuration), but when trying to run server with the domain.xml (basically JAAS info), I get this error:
java.lang.IllegalArgumentException: URI is not absolute
My code is this (error points to the last line):
Server.Builder builder = new Server.Builder("ipc");
EmbeddedFileSystem.Builder efsb = new EmbeddedFileSystem.Builder();
File domainDir = new File( "domains/ipc-domain" );
File domainXML = new File( domainDir.getAbsoluteFile(), "config/domain.xml" );
efsb.instanceRoot( domainDir.getAbsoluteFile() );
efsb.configurationFile( domainXML.getAbsoluteFile() );
EmbeddedFileSystem efs = efsb.build();
builder.embeddedFileSystem(efs);
//Trying to set variable used at domain.xml (blind shot)
Properties props = new Properties();
props.setProperty( "com.sun.aas.instanceRoot" , domainDir.toURI().toString());
Server server = builder.build( props );
My domain.xml (specific part) have this:
<domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" version="10.0">
<system-applications/>
<applications>
<application context-root="/IPC" location="${com.sun.aas.instanceRoot}/applications/IPC/" name="IPC" object-type="user">
<property name="keepSessions" value="false"></property>
<property name="defaultAppName" value="IPC"></property>
<module name="IPC">
<engine sniffer="ejb"></engine>
<engine sniffer="security"></engine>
<engine sniffer="jpa"></engine>
<engine sniffer="web"></engine>
</module>
</application>
</applications>
<resources>
<jdbc-connection-pool pool-resize-quantity="1" datasource-classname="org.apache.derby.jdbc.ClientDataSource" max-pool-size="2" res-type="javax.sql.DataSource" steady-pool-size="1" name="ipc-pool">
<property name="PortNumber" value="1527"></property>
<property name="ServerName" value="0.0.0.0"></property>
<property name="User" value="app"></property>
<property name="Password" value="root"></property>
<property name="DatabaseName" value="IPC"></property>
</jdbc-connection-pool>
<jdbc-resource pool-name="ipc-pool" jndi-name="jdbc/IPC"></jdbc-resource>
</resources>
I've already tried to change the parts related to the "${com.sun.aas.instanceRoot}" variable, but then I have small variations of the URI error. Any insight?

How to properly configure NHibernate event listeners

I'm trying to use an event listener for the first time. All samples I've seen show how easy it is to configure, but for some reason I'm having trouble - it doesn't seem to be called. I suspect I'm missing something obvious.
I've tried this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="TerraCognita.LoanExpress">
<!-- other stuff... -->
<listener type="delete" class="Test.TestDeleteListener, MyDllName" />
</session-factory>
</hibernate-configuration>
as well as:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="TerraCognita.LoanExpress">
<!-- other stuff... -->
<event type="delete">
<listener class="Test.TestDeleteListener, MyDllName" />
</event>
</session-factory>
</hibernate-configuration>
When configuration is loaded and the session factory is built:
var cfg = new NHibernate.Cfg.Configuration();
cfg.AddAssembly("MyDllName");
sessionFactory = cfg.BuildSessionFactory();
After instantiation, cfg.EventListeners.DeleteEventListeners has a single entry, of type DefaultDeleteEventListener (as I'd expect). However, after cfg.AddAssembly is called, this is still the case - but given the configuration, I would expect that the DeleteEventListener should actually be of type TestDeleteListener.
In my unit test, the only way I can get my event listener working is by manually adding it to the session info:
var sess = GetSession();
sess.GetSessionImplementation().Listeners.DeleteEventListeners =
new NHibernate.Event.IDeleteEventListener[] { new TestDeleteListener() };
I know this shouldn't be required, and I should be able to configure it properly. Can anyone shine a light on what I'm doing wrong here?
Your configuration is ok, it's just that you overlooked to call cfg.Configure(). Change your initialization code to this and your fine:
var cfg = new NHibernate.Cfg.Configuration();
cfg.Configure();
cfg.AddAssembly("MyDllName");
sessionFactory = cfg.BuildSessionFactory();