Unauthorized error in Plone test, though content type can be added through the web - plone

I've got a content type based on ATFolder:
ConceptSheetFolderSchema = folder.ATFolderSchema.copy()
ConceptSheetFolderSchema['title'].widget.label = _(u"Title")
ConceptSheetFolderSchema['title'].widget.description = _(u"")
ConceptSheetFolderSchema['title'].storage = atapi.AnnotationStorage()
ConceptSheetFolderSchema['description'].widget.label = _(u"Description")
ConceptSheetFolderSchema['description'].widget.description = _("")
ConceptSheetFolderSchema['description'].storage = atapi.AnnotationStorage()
finalizeATCTSchema(ConceptSheetFolderSchema, folderish=True, moveDiscussion=False)
class ConceptSheetFolder(folder.ATFolder):
"""
This is the central container for concept sheets in the site
"""
implements(IConceptSheetFolder)
portal_type = "Concept Sheet Folder"
_at_rename_after_creation = True
schema = ConceptSheetFolderSchema
title = atapi.ATFieldProperty('title')
description = atapi.ATFieldProperty('description')
atapi.registerType(ConceptSheetFolder, PROJECTNAME)
I can add a ConceptSheetFolder no problem through the Plone interface, but I can't get this basic test to work:
class TestContent(unittest.TestCase):
layer = PROJECT_CONCEPTSHEETS_INTEGRATION_TESTING
def test_hierarchy(self):
portal = self.layer['portal']
# Ensure that we can create the various content types without error
setRoles(portal, TEST_USER_ID, ('Manager',))
portal.invokeFactory('Concept Sheet Folder', 'csf1', title=u"Concept Sheet folder")
portal['csf1'].invokeFactory('project.ConceptSheet', 'cs1', title=u"ConceptSheet")
portal['csf1']['cs1'].invokeFactory('project.ConceptMilestone', 'cs1', title=u"Approved")`
I get a error
Unauthorized: Cannot create Concept Sheet Folder when I try this test. I Googled around a bit and found this Nabble post, leading me to look at isConstructionAllowed() in Plone/CMFCore/TestTools.py. Using pdb, I found that ._queryFactoryMethod(), when run in this context, is returning 'None'.
So it appears the FactoryTool for this type isn't working, at least not in the test. I've got the test in the normal GenericSetup place (types.xml, Concept_Sheet_Folder.xml, factorytool.xml), and I'm at a lost as to what else could be causing this problem. Any ideas?
Bonus question: why does this work in the Plone interface but not in the test?
Edit (Dec 13, 2011): Here's my Concept_Sheet_Folder.xml
<?xml version="1.0"?>
<object name="Concept Sheet Folder"
meta_type="Factory-based Type Information with dynamic views"
i18n:domain="iedea.conceptsheets" xmlns:i18n="http://xml.zope.org/namespaces/i18n">
<property name="title" i18n:translate="">Concept Sheet Folder</property>
<property name="description"
i18n:translate="">A folder which can contain concept sheets.</property>
<property name="content_icon">++resource++conceptsheetfolder_icon.gif</property>
<property name="content_meta_type">Concept Sheet Folder</property>
<property name="product">iedea.conceptsheets</property>
<property name="factory">addConceptSheetFolder</property>
<property name="immediate_view">atct_edit</property>
<property name="global_allow">True</property>
<property name="filter_content_types">True</property>
<property name="allowed_content_types">
<element value="Concept Sheet" />
</property>
<property name="allow_discussion">False</property>
<property name="default_view">view</property>
<property name="view_methods">
<element value="view"/>
</property>
<alias from="(Default)" to="(dynamic view)"/>
<alias from="edit" to="atct_edit"/>
<alias from="sharing" to="##sharing"/>
<alias from="view" to="(selected layout)"/>
<action title="View" action_id="view" category="object" condition_expr=""
url_expr="string:${folder_url}/" visible="True">
<permission value="View"/>
</action>
<action title="Edit" action_id="edit" category="object" condition_expr=""
url_expr="string:${object_url}/edit" visible="True">
<permission value="Modify portal content"/>
</action>
</object>

I've run into this problem myself. The problem is that the your Archetype's factory is not yet properly registered by the time you are trying to create it.
That's why _queryFactoryMethod() returns None, as you found out.
The solution differs a bit on whether you are using Products.ZopeTestCase or the newer plone.app.testing as your testing framework.
However, in both cases you need to make sure that the add-on product that defines the Archetype (ConceptSheetFolder) that you are trying to create (via invokeFactory), has aready been installed.
When using Products.ZopeTestCase:
In the case that you are using Products.ZopeTestCase (and Products.PloneTestCase), you need to call
Products.ZopeTestCase.installProduct
You need to make sure that your installProduct call does not get deferred until after your test is called.
In Plone 4 this means that your installProduct call should not be in an #onsetup decorated function (although this will still work in Plone 3).
This mailing list discussion might further clear things up:
http://plone.293351.n2.nabble.com/invokeFactory-failing-on-Plone-4-PTC-but-working-on-Plone-3-td5755482.html
When using plone.app.testing:
If you are using plone.app.testing, you should call:
plone.testing.z2.installProduct
This should be done in the setUpZope method that you override from the PloneSandboxLayer.
For more info, read the description under setUpZope in plone.app.testing.helpers.py (Line 257)
https://github.com/plone/plone.app.testing/blob/2ef789f8173c695179b043fd4634e0bdb6567511/plone/app/testing/helpers.py

Related

org.hibernate.validator.constraints not picking reloaded messages

I am trying to use Spring's ReloadableResourceBundleMessageSource for LocalValidatorFactoryBean so that when I update an error message it should reflect without requiring the server to be restarted. I am using Spring 4.1.4, hibernate-validator 4.3.2.Final.
Below are the code details -
context.xml -
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource">
<ref bean="messageSource"/>
</property>
</bean>
Model -
import org.hibernate.validator.constraints.NotBlank;
public class InputForm {
#NotBlank ( message = "{required.string.blank}")
String requiredString;
Controller -
#RequestMapping(value = "/check/string", method = RequestMethod.POST)
public String checkString(
#ModelAttribute("formModel") #Valid InputForm inputForm ,
BindingResult result, Model model, HttpServletResponse response,
HttpServletRequest request) {
if (result.hasErrors()) {
model.addAttribute("formModel", inputForm);
return "userInput";
}
// Do some backend validation with String
result.reject("string.not.valid",
"String is Invalid");
model.addAttribute("formModel", inputForm);
return "userInput";
}
application.properties (in /WEB_INF/ folder)
required.string.blank=Please enter the required string.
string.not.valid=Please enter a valid string.
fileapplication.properties (in /conf/ folder. Will override above file)
required.string.blank=You did not enter the required string. #Does not reflect when I change here
string.not.valid=You did not enter a valid string. #Reflects when I change here
Now the problem I am facing is, when I update "string.not.valid" in fileapplication.properties it reflects at runtime and I see the updated message. But when I update "required.string.blank" in fileapplication.properties it does not reflect at runtime.
Note that the overriding part is working fine for both messages upon application start up. But the "reloading" part is not working fine for "required.string.blank".
This is what I figured out based on my research - We need to create our own MessageInterpolator and add it as dependency to the validator instead of message source. Because when we add a messageSource as dependency, it is cached by default by the validator and any message reloads spring does won't take effect in the validator's cached instance of messageSource.
Below are the details:
In context.xml, add the custom MessageInterpolator as dependency to LocalValidatorFactoryBean instead of messageSource:
<mvc:annotation-driven validator="validator" />
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:../conf/fileapplication</value> <!-- Messages here will override the below properties file-->
<value>/WEB-INF/application</value>
</list>
</property>
<property name="cacheSeconds" value="10"></property> <!-- Will check for refresh every 10 seconds -->
</bean>
<bean name="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="messageInterpolator">
<ref bean="messageInterpolator"/>
</property>
</bean>
<bean name="messageInterpolator"
class="com.my.org.support.MyCustomResourceBundleMessageInterpolator">
<constructor-arg ref="messageSource" />
</bean>
Create your custom MessageInterpolator by extending Hibernate's org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.
public class MyCustomResourceBundleMessageInterpolator extends
ResourceBundleMessageInterpolator {
public MyCustomResourceBundleMessageInterpolator(MessageSource messageSource)
{
// Passing false for the second argument
// in the super() constructor avoids the messages being cached.
super(new MessageSourceResourceBundleLocator(messageSource), false);
}
}
Model, Controller and properties file can be same as in the question.

Index error on querying google datastore using gcloud

I am trying to use google datastore for my non GAE application.
For that i have created kinds and ancestor related entities in datastore using gcloud python library.
Also updated datastore index configuration for all the kinds using gcd tool via WEB-INF/datastore-indexes.xml file and its status' are serving.
However i can not successfully query the index based columns either in console or using gcloud lib.
Here is the query & traceback
from gcloud import datastore
ds = datastore.Client(dataset_id='XXXXXX')
query = datastore.Query(ds, kind='event')
query.add_filter('EvtName', '=', 'buy')
query.add_filter('EventDateTime', '<=', datetime.datetime(2015, 10, 22, 8, 45))
for itm in query.fetch():
print(dict(itm))
gcloud.exceptions.PreconditionFailed: 412 no matching index found.
here is my datastore-indexes.xml config
<?xml version="1.0" encoding="utf-8"?>
<datastore-indexes
autoGenerate="false">
<datastore-index kind="event" ancestor="true">
<property name="EvtName" direction="desc" />
<property name="EventDateTime" direction="desc" />
</datastore-index>
<datastore-index kind="att" ancestor="true">
<property name="EvtAttName" direction="desc" />
<property name="EventDateTime" direction="desc" />
</datastore-index>
<datastore-index kind="att_val" ancestor="true">
<property name="AttValue" direction="desc" />
<property name="EventDateTime" direction="desc" />
</datastore-index>
<datastore-index kind="user" ancestor="true">
<property name="EventDateTime" direction="desc" />
</datastore-index>
</datastore-indexes>
am i missing something?
All of your indexes are designed to be used with ancestor queries (note the ancestor=true). However, your actual query does not query within a specific ancestor.
In order to answer your specific query, you need the index:
<datastore-index kind="event" ancestor="false">
<property name="EvtName" direction="desc" />
<property name="EventDateTime" direction="desc" />
</datastore-index>
Or, if you actually do want to query for entities with a specific parent, make sure to add an ancestor filter with Query#hasAncestor(Key parentKey).

Spring: how to get the app's directory path during a bean construction time?

I have a bean as follows:
<bean id="myBean" class="MyBeanClass">
<constructor-arg value="\WEB-INF\myfile.dat"/>
</bean>
In the bean's contructor, I need to build the file's full path. To do that, I have to first find the app's root path first.
Thanks and regards.
Update
Per Michael-O's suggestion, here is my solution (so easy).
Spring bean:
<bean id="myBean" class="MyBeanClass">
<constructor-arg value="/myfile.dat"/> <!--under WEB-INF/classes-->
</bean>
Java:
public MyBeanClass(String path) throws Exception {
ClassPathResource file = new ClassPathResource(path);
lookup = new LookupService(file.getFile().getPath(), LookupService.GEOIP_MEMORY_CACHE);
}
Michael, thanks!!!
Use Spring's Resource class in your bean and spring will do the rest for you.
After seeing #curious1's edit, there is a better solution to his answer. Please do not use that. Go with this one:
beans.xml:
<!-- START: Improvement 2 -->
<context:annotation-config />
<bean id="service" class="LookupService">
<constructor-arg value="classpath:/myfile.dat"/> <!--under WEB-INF/classes-->
<constructor-arg>
<util:constant static-field="LookupService.GEOIP_MEMORY_CACHE"/>
</constructor-arg>
</bean>
<!-- END: Improvement 2 -->
<!-- Spring autowires here -->
<bean id="myBean" class="MyBeanClass" />
<!-- START: Improvement 1 -->
<bean id="myBean" class="MyBeanClass" />
<constructor-arg value="classpath:/myfile.dat"/> <!--under WEB-INF/classes-->
</bean>
<!-- END: Improvement 1 -->
Java:
public MyBeanClass(Resource path) throws Exception {
lookup = new LookupService(path.getInputStream(), LookupService.GEOIP_MEMORY_CACHE);
}
This is source-agnostic, does not rely on files and is the Spring way.
Edit 2: Rethinking my code, it can be even better:
public class MyBeanClass {
#Autowired
LookupService service;
}
and configure LookupService in your beans.xml.
Maybe you should consider using:
getClass().getClassLoader().getResourceAsStream()
inside constructor. This will use your classpath, so you "WEB-INF\myfile.dat", will be visible. Next think is use resource directory to put all resources in one directory (default: under root directory in WAR file)

Debug spring mvc view rendering time

I am currently using Spring MVC 3.x,
and using the freemarker view resolver.
Recently i have been wondering about the execution time that it takes for a view to translate into html before getting sent back as a response. I would like to do tunings if things are slow in this area, which is why i need some numbers.
In plain freemarker mode, i can actually do the simple System.currentTimeMillis() between these to find out the execution time :
long start = System.currentTimeMillis();
// this could be slow or fast depending on the caching used
Template temp = cfg.getTemplate(ftlName);
...
temp.process(model, myWriter); // depends on the writer
System.out.printf("done in %s ms", System.currentTimeMillis() - start);
But how do i do this when with spring mvc's freemaker view rendering ?
You might consider extending org.springframework.web.servlet.view.freemarker.FreeMarkerView and configuring FreeMarkerViewResolver with your custom logging view implementation.
Logging view implementation could look like this:
public class LoggingFreeMarkerView extends FreeMarkerView {
private static final transient Log log = LogFactory.getLog(LoggingFreeMarkerView.class);
#Override
protected void doRender(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
long start = System.currentTimeMillis();
super.doRender(model, request, response);
log.debug("Freemarker rendered " + request.getRequestURI() + " in " + (System.currentTimeMillis() - start) + " ms");
}
}
And wire the view resolver with new class:
<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver" autowire="no">
<property name="viewClass" value="com.example.LoggingFreeMarkerView" />
<property name="cache" value="false" /> <!-- cache disabled for performance monitoring -->
<property name="prefix" value="" />
<property name="suffix" value=".ftl" />
<property name="contentType" value="text/html;charset=utf-8" />
<property name="exposeRequestAttributes" value="true" />
<property name="requestContextAttribute" value="base" />
</bean>
You are going to calculate just on server side merging template with data,Main problem is when freemarker executing on page ,As you know freemarker built on top of jsp page so you should bring code to jsp side to calculate execution time,
As my experience according to data size load time in freemarker is different.
if else condition also is too slow compare to jstl!
I can recommend thymeleaf for spring that allowing templates to be working prototypes on not xml style .

How to add custom error messages in Hibernate validator

I have a simple class like this,
import javax.validation.constraints.NotNull;
import org.hibernate.validator.constraints.Length;
public class Form implements Serializable {
#NotNull
#Length(min = 2, max = 20)
private String lastName;
}
I have messages.properties file in the classpath. It's then loaded via Spring bean as follows,
<bean name="validator"
class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource">
<ref bean="resourceBundleLocator"/>
</property>
</bean>
<bean name="resourceBundleLocator" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath*:messages.properties</value>
</list>
</property>
</bean>
All I want is to get error messages customized according to the bean validated. In other words I want to have each ConstraintViolation object return the error message I have defined in my property file instead of the default one. Is it possible to add message property with a value like this format {xxx.yyyy.zzzz} and refer that message from the messages.properties file ?
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<Form>> inputErrors = validator.validate(form);
If I want to customize the default message for #NotNull and #Length, how can I do that?
My experience on Hibernate validation is zero, Any sample code or step by step guide would be appreciated.
You have this resource bundle file holding the message values.
I think you have to use the path to the i.e. #NotNull annotation
to override the message by hand!
like javax.validation.constraints.NotNull=Notnull error happened!
or something like that!
Look here for that :
Hibernate Validator - The error message
Hope that helps

Resources