Lifefay freemarker ADT: methods unavailable? - java

I'm trying to work on some ADT for asset publisher (Documents and Media type), but I often have a message telling me that :
Expression assetRenderer.getDataRepositoryId is undefined
or
Expression assetRenderer.getFileEntryId is undefined
I found some threads where people said that we must add
velocity.engine.restricted.classes=
velocity.engine.restricted.variables=
freemarker.engine.restricted.classes=
freemarker.engine.restricted.variables=
in portal-ext.properties to get some more classes and variables available, but still I'm not able to call some methods and i don't know why.
I did a
${assetRenderer.getClassName()}
which returns: com.liferay.portlet.documentlibrary.model.DLFileEntry
So I should be able to use any DLFileEntry class public methods (and extended classes), right?
What do I miss?

Asset renderer renders asset entries of the given class (ei. JournalArticle or DLFileEntry in your case). Asset renderer itself is not instance of the given class (in Java sense). It is always instance of com.liferay.portlet.asset.model.AssetRenderer.
To get instance of the related DLFileEntry, you must use DLFileEntryLocalService to find it.
<#-- Obtains instance of DLFileEntryLocalService -->
<#assign DLFileEntryLocalService = serviceLocator.findService("com.liferay.portlet.documentlibrary.service.DLFileEntryLocalService") />
<#-- Function returning underlying DLFileEntry for the given AssetEntry -->
<#function getDLFileEntry assetEntry>
<#return DLFileEntryLocalService.getDLFileEntry(assetEntry.getClassPK())/>
</#function>
Please note, that you need to enable the usage of serviceLocator explicitly by setting freemarker.engine.restricted.variables= in portal-ext.properties.

Related

Need to understand broadleaf commerce custom annotation implementation

I have been trying go through code of Broadleaf Commerce. There were multiple Custom Annotations used however I was not able to locate there Processor. Can anyone help me here. To take example #AdminPresentation it a custom annotation in package org.broadleafcommerce.common.presentation;
However how this is processed throughout the app, I was not able to locate. What I have understood till now we can use Reflection or AOP for its processing. But There was nothing for this.
Please help.
Source code - https://github.com/BroadleafCommerce/BroadleafCommerce
For a short answer, org.broadleafcommerce.openadmin.server.dao.provider.metadata.BasicFieldMetadataProvider#addMetadata is one place that processes those annotations.
On a broader level, the controllers in the openadmin will use the AdminEntityService to get ClassMetaData (all data about how a class should be displayed to an admin user). The #AdminPresentation annotation is one source of this data. The method AdminEntityServiceImpl#getClassMetadata is the main gateway for getting the ClassMetaData.
#getClassMetadata calls #inspect and eventually gets to PersistenceManager#inspect. This method uses the DynamicEntityDao to eventually get to Metadata#getFieldMetadataForTargetClass. That method gets each field of a class via reflection, and then each of those Fields is processed through the available FieldMetadataProviders. The FieldMetadataProviders turn a java.lang.reflect.Field into org.broadleafcommerce.openadmin.dto.FieldMetadata.
Any provided FieldMetadataProvider can contribute field metadata. This metadata is used in the FormBuilderService to construct the admin page.
Class References:
AdminEntityService - org.broadleafcommerce.openadmin.server.service.AdminEntityServiceImpl
PersistenceManager - org.broadleafcommerce.openadmin.server.service.persistence.PersistenceManagerImpl#inspect
DynamicEntityDao - org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl#getPropertiesForEntityClass
Metadata - org.broadleafcommerce.openadmin.server.dao.Metadata#getFieldMetadataForTargetClass
FieldMetadataProvider - org.broadleafcommerce.openadmin.server.dao.provider.metadata.FieldMetadataProvider, org.broadleafcommerce.openadmin.server.dao.DynamicEntityDaoImpl#fieldMetadataProviders
FormBuilderService - org.broadleafcommerce.openadmin.web.service.FormBuilderServiceImpl
Have a look to :
https://www.baeldung.com/java-custom-annotation
You will get explanations about : "default" in the Custom Annotations.
Florent COUDERT.

Eclipse Groovy DSLDs and static compilation

Is it possible to define Eclipse Groovy DSLD (DSL Definition) which can be statically compilable?
I tried to use DSLD example provided by Eclipse, so I created TestDsl.dsld:
contribute(currentType(subType('groovy.lang.GroovyObject'))) {
property (
name : 'newProp',
type : String,
provider : 'Sample DSL',
doc : 'This is a sample. You should see this in content assist for GroovyObjects: <pre>newProp</pre>')
}
Then I wrote a test class using previous property. This class should be compiled statically. Eclipse is showing new property as a valid one, but then it fails to compile.
Same result occurs using both #CompileStatic and #TypeChecked.
DSLDs introduce new methods and properties into content assist and type inferencing. This does not guarantee the methods or properties will be available at compile- or run-time. They operate more like hints than anything.
Quite often, DSLDs are used to fill a gap that exists between the static type checker and the dynamic execution state of your program. If you want something that is compatible with #TypeChecked or #CompileStatic, you may need to write a TypeChekingExtension instead of a DSLD contribution.

xp:checkbox breaks programme

On an XPage I have placed a checkbox group:
<xp:checkBoxGroup
value="#{employeeBean.employee.concern}"
disabled="#{employeeBean.employee.editable eq false}">
<xp:selectItem itemLabel="yes"></xp:selectItem>
<xp:selectItem itemLabel="no"></xp:selectItem>
<xp:selectItem itemLabel="maybe"></xp:selectItem>
</xp:checkBoxGroup>
I have binded the value of the control to field in my Proposal class via a managed bean.
The field concern is of type string and has its out of the box getters and setters.
The problem is whenever I include the data-binding and change values the complete XPage SSJS fails. I do not get an error in the console (server, web client).
Does this have something to do with the type of value the checkbox returns or should I change the type of field in my class?
One thing that springs to mind is the employee object. If this is not set (i.e. there is an instance of the object) then it will fail with a null pointer exception.
In your case it is quite valid the concern field is of type String - obviously you will need a getConcern() and setConcern(String value) method.
Now the real problem is that you cannot see what the server thinks is wrong!
The best way to get to that is to look at the stack traces in the logs. And by far the easiest way to do that is to install the "XPages Log File Reader" application from OpenNTF.org
But my guess is that you haven't created an employee object prior to calling the getEmployee() method to return it ;-)
/John

intellij not resolving el variables within JSP code inspection or autocomplete

To summarize the answer shown here Code assist in (jsp /jstl) view for Spring MVC model objects in Eclipse
is not working for me at all, is there a setting that I need to change ?
I have just downloaded the sample spring-mvc-showcase on github, and it doesn't work out of the box on that project (with either 11.1.3 or EAP 12 version both full enterprise editions), see below (I have no idea where it gets formBean from) :
Here is an example from my own project,the screen shot below (bottom frame) shows my controller adding a string attribute to model and returning correct view name. I would then expect shopString to be offered up as autocomplete option when editing that view, however it is not :
sg is a javascript variable - so great it should be there, but where is "shopString" ?.
Is there a setting I need to change or something else I am missing to get this functionality (using 11.1.3 enterprise edition with all the spring plugins).
It is also failing on spring specific variables :
IS their an open source (one of the spring tutorial projects?) where this definitely works ... or is there a setting I need change in my Intellij install (I have tested with a brand new download of the version 12 EAP) ?
One more screenshot below shows all my spring coifg files set up correctly via autodetection, but the code inspections fails ... this is the spring-mvc-showcase project :
There's a standard way to do this, which is not IntelliJ-specific.
<jsp:useBean id="someModel" scope="request" type="foo.bar.SomeModelClass"/>
The type attribute here does not need to be a concrete class, it can be an interface type as well. Typically you'd put these declarations at the start of your JSP/JSPX files, to provide something like a "declaration of model inputs".
Using JSPs in such a declarative way was recommended in the original book on Spring, in fact (Expert One-on-One J2EE Design and Development.). IntelliJ has been providing full code completion for such pages since at least 7 years.
Note that there are additional relevant convenience features in IntelliJ: if an EL variable reference is marked as undefined, you can press Alt-Enter to select a QuickFix, which will insert a declaration like above. It will even try to figure out the actual type, based on the properties you're accessing.
As I understand Spring, there is no declaration for definitions of variables that you may put into your model. The call model.addAttribute() may add an object to the model, either identified by a parameter or automatically generated by the class name of the object.
So imagine the following case where you have more than one method:
#RequestMapping("foo") public String foo(Model model) {
model.addAttribute("model", new Foo());
return new Random().nextBoolean() ? "page" : "someOtherPage";
}
#RequestMapping("bar") public String bar(Model model) {
model.addAttribute("model", new Bar());
model.addAttribute("model", new Foo());
model.addAttribute("model", new Bar());
return new Random().nextBoolean() ? "page" : "someOtherPage";
}
and the JSP would be something like
<c:out ${model.value} />
Since there is no proper mapping of which controllers may under some circumstances forward to which views, nor what exactly lies within the model, your IDE has no real chance to provide you with proper information.
But to support the IDE in suggesting you some useful information, you can use type hints. Therefore, you have to copy the whole reference of an object, e. g. foo and add a JSP comment like:
<%--#elvariable id="foo" type="com.mycompany.SomeObject"--%>
The warning will vanish and the full IDE support is on your side, allowing you to traverse the fields of foo.
One of the nicest things is that the unused getter warnings will vanish, too. You can directly call the show usages action directly from the JSP or the POJO.
This also works with JSF and particularly within JSF components. Pretty neat feature to have this kind of code completion, showing warnings and errors.
Hope that helps you with your switch to Intellij Idea.
Edit: I also reported this finding to a friend wo wrapped the whole thing into a nice blog entry. Maybe you're interested in reading it: open link
This got fixed in the latest release of intellij 122.694
I faced with similar issue when start writing my own interceptor. Problem was that I start using refference in my view resolver configuration
don't use contruction like this
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" ref="prefix"/>
<property name="suffix" ref="suffix"/>
</bean>-

Grails nested domains - addAll errors to top level domain object

I have a Grails domain like this:
class User {
....
Address address
}
While saving the user, I want to validate the Address object as well and add all errors of Address object to the User object itself.
I am trying to write a custom validator wherein I do it.validate(), but I am not able to find a way to "addAll" the error messages of address.
This discussion below on the grails mailing list about calling validation on child objects and appends them to a single errors list that might work for you.
Form validation with children
If Address has static belongsTo = [user:User] then calling User.validate() or User.save() should also call validation on Address. I've not tried collecting errors on a child object into the parent object's errors list, but for a simple one-to-one association you may not need to, and simply display the errors something like this:
<g:if test="${user?.hasErrors() || user.address?.hasErrors()}">
<div class="errors">
<g:hasErrors bean="${user}">
<g:renderErrors bean="${user}" as="list" />
</g:hasErrors>
<g:hasErrors bean="${user?.address}">
<g:renderErrors bean="${user?.address}" as="list" />
</g:hasErrors>
</div>
</g:if>
Since this is probably a frontend related task, I would not try to fiddle with those error classes. I advance you to just call the validate function within the custom validator like this:
address(validator: { val, obj ->
val?.validate();
});
In the GUI you will find your error messages for the nested domain class within the instance of the nested domain class. Therefore you need to pass the domain class to the GSP.
<g:renderErrors bean="${address}" field="street" />
However if you really want to get a new collection having all errors inside of all nested classes you can have a look at the plugin http://www.grails.org/plugin/extended-validation. With this plugin you have an additional error set, which contains all error messages of nested domain classes (if it is configured to do like this):
user.allErrorsRecursive()
But to be honest, I have not tested it yet ;)

Categories

Resources