Is there a way to create entirely new schema on every case?
Using #DatabaseTearDown annotation is not the case here because i need to reset
id generators as some of my test expectation rely on them (maybe it's a bad practice)
Update on rearrange my tests:
In one of my expected datasets i have:
<field oid="1" type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"/>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
where oid in term table is the generated id. I want to be sure that there are 3 rows were created in field_enum_element table but if i omit generated ids from expected data set as follows:
<field type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"/>
<field_enum_element></field_enum_element>
<field_enum_element></field_enum_element>
<field_enum_element></field_enum_element>
spring-test-db-unit thinks that there are 0 rows in the table
UPDATE:
#Test
#DatabaseSetup(value = "fieldServiceImplTest/testCreateEnumField.xml")
#ExpectedDatabase(value = "fieldServiceImplTest/testCreateEnumField.expected.xml",
assertionMode = DatabaseAssertionMode.NON_STRICT)
#DatabaseTearDown(value = "fieldServiceImplTest/clear.xml", type = DELETE_ALL)
public void testCreateEnumField() {
FieldDTO fieldDTO = new FieldDTO();
fieldDTO.setName("simple enum field");
fieldDTO.setType("enumerated");
fieldDTO.setLevel("term");
fieldDTO.setIsValueRequired(false);
fieldDTO.setDictionaryId(dictionaryService.findByOid(1L).get().returnIdentity());
List<ItemDTO> itemDTOs = Arrays.asList(new ItemDTO(null, "complete"), new ItemDTO(null, "draft"), new ItemDTO(null, "deleted"));
fieldDTO.setItems(new HashSet<>(itemDTOs));
fieldService.createField(fieldDTO);
}
testCreateEnumField.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset>
<dictionary changed="2014-01-31 18:11:54" oid="1" client_oid="1" descr="descr" name="dictionary"/>
</dataset>
testCreateEnumField.expected.xml
<?xml version="1.0" encoding="UTF-8"?>
<dataset reset_sequences="hibernate_sequence">
<dictionary changed="2014-01-31 18:11:54" oid="1" client_oid="1" descr="descr" name="dictionary"/>
<field client_oid="1" oid="1" type="enumerated" name="simple enum field"
dict_oid="1" required="0"
level="1"></field>
<enum_element oid="11" client_oid="1" value="deleted"></enum_element>
<enum_element oid="12" client_oid="1" value="draft"></enum_element>
<enum_element oid="13" client_oid="1" value="complete"></enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
<field_enum_element field_oid="1"></field_enum_element>
</dataset>
Ideally i would like to be able to drop sequence between tests and test cases.
Although I don't exactly know what your use case is, it sounds like it's a good fit for trying the new declarative SQL feature in Spring 4.1 RC1. Here is the JIRA issue that describes what this new feature.
Your code would look something like:
#Test
#Sql("fix-sequence.sql")
public void test() {
//whatever
}
You can find the Javadoc of #Sql here.
Inside fix-sequence.sql you would provide the SQL needed for resetting the db for the tests
I was able to manage the problem by doing a little workaround by dropping sequence table in #Before method with simple native sql query: "drop table hibernate_sequence".
Actually, the better solution is just to include <hibernate_sequence next_val="1"/> into test dataset at #DatabaseSetup phase
Related
I need to export a solution from PowerApps (model driven), version 9.2
and import it to CRM, version 9.1.
I have an error because of this version. How can I do this?
You need to export the solution for a previous target version.
In .NET/C# you can do this using the ExportSolutionRequest:
public string ExportSolution(string solutionName, bool asManaged)
{
var request = new ExportSolutionRequest
{
SolutionName = solutionName,
Managed = asManaged,
TargetVersion = "9.1"
};
var response = _service.Execute(request) as ExportSolutionResponse;
string solutionZipPath = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
File.WriteAllBytes(solutionZipPath, response.ExportSolutionFile);
return solutionZipPath;
}
In the example above _service is of type IOrganizationService.
Another solution would involve a tweak:
Export the solution.
Extract the solution zip.
Open the solution.xml manifest in a text editor.
In the root ImportExportXml element change the value of attribute SolutionPackageVersion into the desired version.
Save your changes.
Zip the solution.
Import the modified solution in the target environment.
<?xml version="1.0" encoding="utf-8"?>
<ImportExportXml version="9.2.21082.140" SolutionPackageVersion="9.2" languagecode="1033" generatedBy="CrmLive" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<SolutionManifest>
...
</SolutionManifest>
</ImportExportXml>
Last approach does not guarantee the solution can be imported without issues as it can contain features not supported by a previous version. However, sometimes it is possible to remove these features by hand.
Refer to this post for a description of the feature.
My HTML cache is enabled, and I have turned on "Clear on Index Update" for one of my Renderings.
However, the entry for my Rendering is NOT marked with any special token in the cache - I verified the cache content before and after using the rendering. This, of course, leads to the Clear() method in Sitecore.ContentSearch.Maintenance.IndexDependentHtmlCacheManager to not pick it up, making this feature useless.
I am on Sitecore 7.2 - is this a known bug?
You can override GenerateCacheKey processor (or add your own processor after that one) and update the key to include _#index.
Code below is for MVC. As #jammykam says, in WebForms key is added to cacheKey OOTB.
public class GenerateCustomCacheKey : GenerateCacheKey
{
protected override string GenerateKey(Rendering rendering, RenderRenderingArgs args)
{
Item renderingItem = rendering.RenderingItem.InnerItem;
var key = base.GenerateKey(rendering, args);
if (renderingItem["ClearOnIndexUpdate"].ToBool())
key += "_#index";
return key;
}
}
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<mvc.renderRendering>
<processor
type="My.Assembly.Namespace.GenerateCustomCacheKey, My.Assembly"
patch:instead="*[#type='Sitecore.Mvc.Pipelines.Response.RenderRendering.GenerateCacheKey, Sitecore.Mvc']" />
</mvc.renderRendering>
</pipelines>
</sitecore>
</configuration>
Ok, it turns out that this features is currently bugged on MVC, at least as of 16th of March 2015:
http://www.tarasalenin.com/caching-sitecore-mvc-renderings/
That's about it. There are workarounds, but in the meanwhile I sorted my problem in a different way. Posting this in case someone else happens to have the same problem.
I'm using Selenium Webdriver (ver 2.31.2.0) (.Net) and I'm trying to extract an element (XML) which is returning from the `driver.PageSource'.
My Question: How to get the list of items using the below xpath.
I able to play in FF using XPATH addons but the same code does not work in Selenium Webdriver
any help?
Here is my code in Selenium Webdriver:
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
string _page_source = driver.PageSource;
ReadOnlyCollection<IWebElement> webElements = _page_source.FindElementsByXPath("//response//results//items/vList");
my xml looks like this:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<meta>
</meta>
<results i:type="vList">
<name>Language</name>
<queryValue>language</queryValue>
<displayOrder>0</displayOrder>
<items>
<vList>
<name>English</name>
<displayName>English</displayName>
<displayOrder>0</displayOrder>
<items />
</vList>
<vList>
<name>Swedish</name>
<displayName>Swedish</displayName>
<displayOrder>1</displayOrder>
<items />
</vList>
</items>
</results>
</response>
You can use selenium to browse to and obtain the xml, but work with the xml using .net classes.
The driver.PageSource property is a string, and you should use .Net classes directly to parse the xml represented. Also, there is no method FindElementsByXPath() on a string object, unless this is an extension method that you have written.
Read the xml using the driver.PageSource from selenium
var driver = new FirefoxDriver();
driver.Navigate().GoToUrl("http://website_name/languages.xml");
XmlReader reader = XmlReader.Create(driver.PageSource);
Or, read the xml by directly browsing to the url using
XmlReader reader = XmlReader.Create("http://website_name/languages.xml");
And then use below code to parse and read the xml.
Key point to note is how the namespace information is provided to the xpath.
//load xml document
XElement xmlDocumentRoot = XElement.Load(reader);
//also add the namespace infn, chose a prefix for the default namespace
XmlNameTable nameTable = reader.NameTable;
XmlNamespaceManager namespaceManager = new XmlNamespaceManager(nameTable);
namespaceManager.AddNamespace("a", "http://schemas.datacontract.org/2004/07/myproj.cnn.com");
//now query with your xml - remeber to prefix the default namespace
var items = xmlDocumentRoot.XPathSelectElements("//a:results/a:items/a:vList", namespaceManager);
Console.WriteLine("vlist has {0} items.", items.Count());
foreach (var item in items)
{
Console.WriteLine("Display name: {0}", item.XPathSelectElement("a:displayName",namespaceManager).Value);
}
// OR get a list of all display names using linq
var displayNames = items.Select(x => x.XPathSelectElement("a:displayName", namespaceManager).Value).ToList();
You will need the following namespaces for the above to work:
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
The XML input you have posted has a namespace declared: xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com". See the next line:
<response xmlns="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
Because this namespace has no prefix it is the default namespace for all elements without a prefix. Which means element <response> and element <results> etc all belong to this namespace.
Read next: http://www.w3schools.com/xml/xml_namespaces.asp
So in you code you need to declare the namespace before any XPath evaluation will work. I do not know how to set the namespace in Selenium Webdriver but you can find it I guess.
Once you declared the namespace you need to use this in your XPath. For example in a XSLT you can declare the namespace as follows:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:foo="http://schemas.datacontract.org/2004/07/myproj.cnn.com">
I now declared the namespace with prefix foo. The XPath that can be used to retrieve all vList elements would be:
/foo:response/foo:results/foo:items/foo:vList
To get all displayName elements you can use:
/foo:response/foo:results/foo:items/foo:vList/foo:displayName
If you want the total count of the elements instead of the list of elements, you can wrap count() around it like:
count(/foo:response/foo:results/foo:items/foo:vList)
count(/foo:response/foo:results/foo:items/foo:vList/foo:displayName)
The XPath you used has a lot of // in it. Only use // if it is really necessary, because it will scan the complete file and takes more resources than necessary if you know the path already.
I'm interested in creating a Maven archetype, and I think I have most of the basics down. However, one thing I'm stuck on is that sometimes I want to use custom logic to fill in a template. For example, if somebody generates my archetype and specifies the artifactId as hello-world, I'd like to generate a class named HelloWorld that simply prints out "Hello World!" to the console. If another person generates it with artifactId = howdy-there, the genned class would be HowdyThere and it would print out "Howdy There!".
I know that under the covers, Maven's archetype mechanism leverages the Velocity Template Engine, so I read this article on creating custom directives. This seemed to be what I was looking for, so I created a class called HyphenatedToCamelCaseDirective that extends org.apache.velocity.runtime.directive.Directive. In that class, my getName() implementation returns "hyphenatedCamelCase". In my archetype-metadata.xml file, I have the following...
<requiredProperties>
<requiredProperty key="userdirective">
<defaultValue>com.jlarge.HyphenatedToCamelCaseDirective</defaultValue>
</requiredProperty>
</requiredProperties>
My template class looks like this...
package ${package};
public class #hyphenatedToCamelCase('$artifactId') {
// userdirective = $userdirective
public static void main(String[] args) {
System.out.println("#hyphenatedToCamelCase('$artifactId')"));
}
}
After I install my archetype and then do an archetype:generate by specifying artifactId = howdy-there and groupId = f1.f2, the resulting class looks like this...
package f1.f2;
public class #hyphenatedToCamelCase('howdy-there') {
// userdirective = com.jlarge.HyphenatedToCamelCaseDirective
public static void main(String[] args) {
System.out.println("#hyphenatedToCamelCase('howdy-there')"));
}
}
The result shows that even though userdirective is being set the way I expected it to, It's not evaulating the #hyphenatedToCamelCase directives like I was hoping. In the directive class, I have the render method logging a message to System.out, but that message doesn't show up in the console, so that leads me to believe that the method never got executed during archetype:generate.
Am I missing something simple here, or is this approach just not the way to go?
The required properties section of the archetype-metatadata xml is used to pass additional properties to the velocity context, it is not meant for passing velocity engine configuration. So setting a property called userDirective will only make the variable $userDirective availble and not add a custom directive to the velocity engine.
If you see the source code, the velocity engine used by maven-archetype plugin does not depend on any external property source for its configuration. The code that generates the project relies on an autowired (by the plexus container) implementation of VelocityComponent.
This is the code where the velocity engine is initialized:
public void initialize()
throws InitializationException
{
engine = new VelocityEngine();
// avoid "unable to find resource 'VM_global_library.vm' in any resource loader."
engine.setProperty( "velocimacro.library", "" );
engine.setProperty( RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, this );
if ( properties != null )
{
for ( Enumeration e = properties.propertyNames(); e.hasMoreElements(); )
{
String key = e.nextElement().toString();
String value = properties.getProperty( key );
engine.setProperty( key, value );
getLogger().debug( "Setting property: " + key + " => '" + value + "'." );
}
}
try
{
engine.init();
}
catch ( Exception e )
{
throw new InitializationException( "Cannot start the velocity engine: ", e );
}
}
There is a hacky way of adding your custom directive. The properties you see above are read from the components.xml file in the plexus-velocity-1.1.8.jar. So open this file and add your configuration property
<component-set>
<components>
<component>
<role>org.codehaus.plexus.velocity.VelocityComponent</role>
<role-hint>default</role-hint>
<implementation>org.codehaus.plexus.velocity.DefaultVelocityComponent</implementation>
<configuration>
<properties>
<property>
<name>resource.loader</name>
<value>classpath,site</value>
</property>
...
<property>
<name>userdirective</name>
<value>com.jlarge.HyphenatedToCamelCaseDirective</value>
</property>
</properties>
</configuration>
</component>
</components>
</component-set>
Next add your custom directive class file to this jar and run archetype:generate.
As you see this is very fraglie and you will need to figure a way to distribute this hacked plexus-velocity jar. Depending on what you are planning to use this archetype for it might be worth the effort.
My batched statements in mybatis are timing out. I'd like to throttle the load I'm sending to the database by flushing the statements periodically. In iBATIS, I used a callback, something like this:
sqlMapClientTemplate.execute(new SqlMapClientCallback<Integer>() {
#Override
public Integer doInSqlMapClient(SqlMapExecutor executor)
throws SQLException {
executor.startBatch();
int tally = 0;
for (Foo foo: foos) {
executor.insert("FooSql.insertFoo",foo.getData());
/* executes batch when > MAX_TALLY */
tally = BatchHelper.updateTallyOnMod(executor, tally);
}
return executor.executeBatch();
}
});
Is there a better way to do this in mybatis? Or do I need to do the same type of thing with SqlSessionCallback? This feels cumbersome. What I'd really like to do is configure the project to flush every N batched statements.
I did not get any responses, so I'll share the solution I settled on.
Mybatis provides direct access to statement flushing. I autowired the SqlSession, used Guava to partition the collection into manageable chunks, then flushed the statements after each chunk.
Iterable<List<Foo>> partitions = Iterables.partition(foos, MAX_TALLY);
for (List<Foo> partition : partitions) {
for (Foo foo : partition) {
mapper.insertFoo(foo);
}
sqlSession.flushStatements();
}
Sorry for the late response, but I just stumbled onto this question right now. However, hopefully it will help others with a similar problem.
You don't need to explicitly Autowire the SqlSession. You may use the mapper interface itself. In the mapper interface simply define a method that is annotated with the #Flush annotation and has a return type of List<BatchResult>. Here's an example of a method in the mapper interface:
#Flush
List<BatchResult> flushBatchedStatements();
Then simply call this method on your mapper object like so:
Iterable<List<Foo>> partitions = Iterables.partition(foos, MAX_TALLY);
for (List<Foo> partition : partitions)
{
for (Foo foo : partition)
{
mapper.insertFoo(foo);
}
mapper.flushBatchedStatements(); //this call will flush the all statements batched upto this point, into the table.
}
Note that you don't need to add anything special into your mapper XML file to support this type of statement flushing via the mapper interface. Your XML mapper may simply be something like
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace=".....">
<insert id="bulkInsertIntoTable" parameterType="myPackage.Foo">
insert into MyDatabaseTable(col1, col2, col3)
values
( #{fooObj.data1}, #{fooObj.data2}, #{fooObj.data3} )
</insert>
</mapper>
The only thing that is needed is that you use MyBatis 3.3 or higher. Here's what the MyBatis docs on the MyBatis website state:
If this annotation is used, it can be called the
SqlSession#flushStatements() via method defined at a Mapper
interface.(MyBatis 3.3 or above)
For more details please visit the MyBatis official documentation site:
http://www.mybatis.org/mybatis-3/java-api.html