Saturday 23 March 2013

How to: create a new component with Talend Open Studio

Yesterday I was searching for a good tutorial in order to learn the basics of component creation with Talend Open Studio (I needed to do a custom scheduling of reports, and Jasperserver simply wouldn't let me do it).
Check out this link:
http://www.powerupbi.com/talend/componentCreation_1.html
In just a couple of hours, I was able to understand the the basics and I managed to create my very first component. Kudos to the author, it's pretty straightforward!

Thursday 29 November 2012

How to stop the Forticlient Scheduler

Last Friday I installed Forticlient SSL VPN in order to connect to one of my client's pc remotely. I immediately noticed that Forticlient VPN disconnected automatically all of my other active VPNs, but at the time thought nothing of it.
Today I wanted to connect with my OpenVPN account, but could not do it because the Forticlient VPN and Forticlient Scheduler services were configured to start at Windows boot: I opened the Windows Services utility and tried to set the startup type of both processes to "Manual", but the FortiClient Scheduler kept giving me the error: Parameter is incorrect
After much searching on internet for solutions, I found out that FortiClient Scheduler is used by an active service called FortiShield, and that's why I could neither stop nor disable the process even with administrator rights; so I opened a window console and typed this:


After this I could stop the FortiClient Scheduler and set its startup type to "Manual". I hope this post will help others with the same problem!

Thursday 15 November 2012

Querydsl

Yesterday I attended a Spring Data Webinar, talking about the latest updates about JPA, JDBC and REST support.
In particular, Spring JPA added support for Querydsl predicates and type-safe JPA queries. Being a JPA user (but not a Spring JPA) I didn't know about this framework, but I find it particularly useful :)

More on: http://www.querydsl.com/

Wednesday 14 November 2012

I hate you, Javascript

But not as much as the people who's got the great idea to insert special characters in some Oracle tables! It took me half a day to correctly decode the parameters I got from the url and to make Oracle read them.
What I learned today:

  1. The javascript "unescape" function is super,super great... alone it resolves the majority of the issues of url encoding :)
  2. On the other side, accented characters are a bitch... you never know what you're going to come up with (for example, 'à' becomes 'Ã '... and don't forget the space!!!)
  3. Last but not the least: be sure to replace your special characters in the correct way. If you have to pass a query string to a db, be sure to use the html number, NOT the html name! This link is great to have on hand: http://www.ascii.cl/htmlcodes.htm
A lot of effort and time later, I finally got the point I wanted on my map:


Tuesday 13 November 2012

Look at that... it's been nearly a year since my last post.
Unfortunately, I have been very busy with work and, I admit, I kinda forgot about this blog :)
To remedy that, here's a photo of me during the last Lucca Comics and Games last week!



Friday 4 November 2011

iReport: how to add "All values" option inside an input control

This is a simple but effective workaround for iReport that adds the "All values" option inside a "single select query" or "multi select query" input control type.

  • First of all, in iReport we create a new parameter and we give it as default the string "All values" (or anything similar you may want to see in the input control)
  • Now we have to edit the source query of the report like this:
SELECT ... FROM ... 
WHERE ([COLUMN_TO_FILTER] = $P{parameter} OR ${parameter} = "All values")


$P{parameter} is the parameter we have just created, and [COLUMN_TO_FILTER] contains the list of values of the input control.

  • Now we can upload the report to JasperReports Server and start creating our input control like this:
    • Type: Single Select Query (or Multi-Select Query)
    • Check the "Mandatory" and "Visible" options
    • Query Resource: select "Locally defined" and click on "Edit Local Resource"
    • In tab Query write a source query like this:
SELECT DISTINCT [COLUMN_TO_FILTER] FROM ...

UNION
SELECT "All values" FROM DUAL
ORDER BY [COLUMN_TO_FILTER]

  • Complete the parameter definition as usual and save it
  • When you test the report and JasperReports Server, you'll see the option "All values" (because we added it manually in the input control query) and it'll correctly let you see the complete list of available values for the report

Thursday 27 October 2011

How to: interface JasperReports Server and LDAP (2/2)

Multi-tenancy option


As predefined option, JasperReports Server maps all external users inside organization_1. If you want to simply change the destined organization:

  • Open the file /jasperserver-pro/WEB-INF/applicationContext-multiTenancy-security.xml
  • Locate the bean defaultExternalUserProcessor
  • Modify the property defaultOrganizationIfNotDetected (as shown below)
<bean id="defaultExternalUserProcessor" class="com.jaspersoft.jasperserver.multipleTenancy.DefaultExternalUserProcessor">
<property name="multiTenancyService"><ref bean="internalMultiTenancyService"/></property>
<property name="defaultOrganizationIfNotDetected" value="organization_1"/>
        <property name="multiTenancyConfiguration"><ref bean="multiTenancyConfiguration"/></property>
        <property name="rootOrganizationRolesMap">
            <map>
                <!-- Mapping customers roles to JS roles Example -->
                <!--<entry>-->
                    <!--<key>-->
                       <!-- Сustomer role(with adding ROLE_ prefix) which need to be mapped to root JS roles -->
                       <!--<value>ROLE_ADMIN</value>-->
                    <!--</key>-->
                       <!-- root JS role customer role to be mapped to -->
                       <!--<value>ROLE_ADMINISTRATOR</value>-->
                <!--</entry>-->
            </map>
        </property>
</bean>

WARNING: if you don't specify anything in defaultOrganizationIfNotDetected, the external users will be mapped inside the root folder and will have the same visibility as superuser!
If you want instead to map on JasperReports Server the LDAP directory structure we have to proceed as follows:

  • Open the file /jasperserver-pro/WEB-INF/applicationContext-multiTenancy-security.xml
  • Locate the bean mtUserAuthorityServiceTarget
  • Locate the property userProcessors
  • Uncomment the ldapExternalUserProcessor reference and comment defaultExternalUserProcessor
<bean id="mtUserAuthorityServiceTarget"
        class="com.jaspersoft.jasperserver.multipleTenancy.MTUserAuthorityServiceImpl">
        <property name="sessionFactory" ref="sessionFactory"/>
        <property name="objectMappingFactory" ref="mappingResourceFactory"/>
        <property name="persistentClassFactory" ref="persistentMappings"/>
        <property name="profileAttributeService" ref="profileAttributeService"/>
        <property name="defaultInternalRoles">
          <list>
            <value>ROLE_USER</value>
          </list>
        </property>
        <property name="multiTenancyConfiguration"><ref bean="multiTenancyConfiguration"/></property>
        <property name="securityProvider"><ref local="tenantSecurityProvider"/></property>
        <property name="securityContextProvider"><ref bean="${bean.securityContextProvider}"/></property>
        <property name="tenantPersistenceResolver"><ref bean="${bean.hibernateTenantService}"/></property>
        <property name="userProcessors">
            <list>
                <!-- For LDAP authentication -->
                <ref bean="ldapExternalUserProcessor"/>
                <!--ref bean="defaultExternalUserProcessor"/-->
            </list>
        </property>
        <property name="auditContext" ref="${bean.auditContext}"/>
        <property name="databaseCharactersEscapeResolver" ref="databaseCharactersEscapeResolver"/>
        <property name="defaultExternalUserProcessor" ref="defaultExternalUserProcessor"/>
</bean>


  • Find the bean ldapExternalUserProcessor and uncomment it
  • Add the following informations:
    • excludeRootDN: specify if the baseDN (inside the connection parameters) should be mapped with the RDN (in our example, if the folders com and maxcrc should be created or not)
    • organizationsRDN: a list of attributes which will be mapped as organization names. If this list is empty or there is no match between this list and the LDAP directory, the organization name will be determined solely by the excludeRootDN and rootOrganizationId properties
    • rootOrganizationId: the organizationId under which the organizations mapped from the LDAP directory will be created. If empty, it's root
    • rootOrganizationRolesMap: a useful property if you want to map JasperReports Server system roles with the ones defined in LDAP (see below)
<!-- For LDAP authentication -->
<bean id="ldapExternalUserProcessor" class="com.jaspersoft.jasperserver.multipleTenancy.ldap.LdapExternalUserProcessor">
<property name="ldapContextSource" ref="ldapContextSource"/>
<property name="multiTenancyService"><ref bean="internalMultiTenancyService"/></property>
<property name="excludeRootDn" value="true"/>
<!-- only following RDNs will matter in creating of organization hierarchy -->
<property name="organizationRDNs">
<list>
<!--<value>dc</value>-->
<!--<value>c</value>-->
<value>ou</value>
<value>o</value>
<!--<value>st</value>-->
</list>
</property>
<property name="rootOrganizationId" value=""/>
        <property name="multiTenancyConfiguration"><ref bean="multiTenancyConfiguration"/></property>
        <property name="rootOrganizationRolesMap">
            <map>
            </map>
        </property>
</bean>

In our example:

  • excludeRootDN: true (we don't want to create com and maxcrc folders)
  • organizationsRDN: o, ou (we want to map a first-level organization named People and two second-level organizations: jobs and users)
  • rootOrganizationId: null (we want People to be a first-level organization)
WARNING(1): if we have rootOrganizationId = null, excludeRootDN = true and no match between the attributes in organizationsRDN and the LDAP directory structure, the external users will be mapped inside the root folder and will have the same visibility as superuser!
WARNING(2): it's necessary to create beforehand the People folder: jobs and users will be created at the first login of either paul or tom

Role Mapping


In order to find user roles, LDAP makes a second search inside the directory structure: in order to specify search parameters, we have to proceed as follows:

  • Open the file /jasperserver-pro/WEB-INF/applicationContext-security.xml
  • Locate the bean ldapAuthenticationProvider
  • In the second constructor add the following informations:
    • constructor-arg index="1": a branch of the LDAP directory where the roles are defined. If empty, LDAP will cover the entire directory tree
    • groupRoleAttribute: the attribute whose value is the role name to map
    • groupSearchFilter: a filter search. In this case, the expression {0} is the complete DN of the username (ex: cn=tom,o=users,ou=People,dc=maxcrc,dc=com), while the expression {1} is the username specified in the login page (ex: tom)
    • searchSubTree: a flag that indicates whether or not the search should extend to eventual children nodes
    • convertToUpperCase: a flag that indicates whether the group name should be converted to upper case when used as a role name in JasperReports Server (the default is true)
    • rolePrefix: a prefix to the group name to add when creating a Jasper role (the default is ROLE_)
To all users will be assigned the predefined role ROLE_USER at the first access.



<!-- For LDAP authentication -->
   
   <bean id="ldapAuthenticationProvider" class="org.springframework.security.providers.ldap.LdapAuthenticationProvider">
     <constructor-arg>
       <bean class="org.springframework.security.providers.ldap.authenticator.BindAuthenticator">
          <constructor-arg><ref local="ldapContextSource"/></constructor-arg>
          <!-- property name="userDnPatterns"><list><value>uid={0}</value></list></property -->
          <property name="userSearch" ref="userSearch"/>
       </bean>
     </constructor-arg>
     <constructor-arg>
       <bean class="org.springframework.security.ldap.populator.DefaultLdapAuthoritiesPopulator">
          <constructor-arg index="0"><ref local="ldapContextSource"/></constructor-arg>
          <constructor-arg index="1"><value>o=group,ou=departmentGroups</value></constructor-arg>
          <property name="groupRoleAttribute"><value>cn</value></property>
          <!--<property name="groupSearchFilter"><value>
(&amp;(uniqueMember={0})(objectclass=groupOfUniqueNames))</value></property>-->
          <property name="searchSubtree"><value>false</value></property>            
       </bean>
     </constructor-arg>
   </bean>


In our example:

  • constructor-arg index="1": o=group, ou=departmentGroups
  • groupRoleAttribute: cn
  • groupSearchFilter: nothing (JasperReports will user the member attribute as a filter if nothing is specified)
  • searchSubTree: false
System Role Mapping


Once you have tested that JasperReports Server creates the roles defined externally in the LDAP directory, it's possible to map these roles to the predefined system ones in JasperReports Server: for example, in our case we want to associate ROLE_DEVELOPER to ROLE_ADMINISTRATOR.
WARNING: with this procedure user paul won't have the ROLE_DEVELOPER anymore, just ROLE_ADMINISTRATOR; therefore, it's best to delete ROLE_DEVELOPER or user paul entirely if already present, in order to avoid Jasper launching an IllegalArgumentException.

  • Open the file /jasperserver-pro/WEB-INF/applicationContext-multiTenancy-security.xml
  • Locate the bean defaultExternalUserProcessor (if you are mapping the users inside a single organization) or ldapExternalUserProcessor (if you are using multi-Tenancy)
  • Locate the property rootOrganizationRolesMap and map the LDAP role to the corresponding Jasper role, as shown below



<!-- For LDAP authentication -->
<bean id="ldapExternalUserProcessor" class="com.jaspersoft.jasperserver.multipleTenancy.ldap.LdapExternalUserProcessor">
<property name="ldapContextSource" ref="ldapContextSource"/>
<property name="multiTenancyService"><ref bean="internalMultiTenancyService"/></property>
<property name="excludeRootDn" value="true"/>
<!-- only following RDNs will matter in creating of organization hierarchy -->
<property name="organizationRDNs">
<list>
<!--<value>dc</value>-->
<!--<value>c</value>-->
<value>ou</value>
<value>o</value>
<!--<value>st</value>-->
</list>
</property>
<property name="rootOrganizationId" value=""/>
        <property name="multiTenancyConfiguration"><ref bean="multiTenancyConfiguration"/></property>
        <property name="rootOrganizationRolesMap">
            <map>
<entry>
<key>
<value>ROLE_DEVELOPER</value>
</key>
<value>ROLE_ADMINISTRATOR</value>
</entry>
            </map>
        </property>
</bean>