mercoledì 2 luglio 2014

preventDefault and stopPropagation for anchors in AngularJS

Sometimes in an application we use anchor tags to trigger functions on our controller like the following:

<a href="#" data-ng-click="doSomething()">Click me</a<>

This is not a best practice, but in some cases you need to use it anyways. In this case you need to tell the browser to not to handle the anchor like a link and reload the page.

In plain javascript is really simple:

HTML
<a href="#" onclick="doSomething()">Click me</a>

Javascript
...
function doSomething(event)
{
    event.preventDefault();
    event.stopPropagation();

    alert("Hello, world!");
}
...

But now, you want to do this with AngularJS. It's really simple, like in plain javascript. So, you'll write:

HTML
<a href="#" data-ng-click="doSomething(); $event.preventDefault(); $event.stopPropagation();">Click me</a>

Javascript
...
$scope.doSomething = function()
{
    alert("Hello, world!");
}
...

lunedì 26 maggio 2014

JavaScript e AngularJS: plugin utili per lo sviluppo

Vi propongo un paio di plugin utili per lo sviluppo su AngularJS e JavaScript in generale.
  • Chrome:
    • Angular Scope Inspector
      Inspector per l'analisi delle informazioni e delle funzioni contenute negli scope
    • ng-inspector for AngularJS
      Inspector che mostra l'elenco degli scope, dei controller e delle direttive associate adogni scope.
    • JavaScript Errors Notifier
      Mostra un simbolo nella barra degli indirizzi quando avviene un errore javascript.
    • Web Developer
      Barra che mostra diverse utility (Ridimensionamento pagina, blocco cache, etc).
    • jQuery Debugger
      Mostra, tra gli strumenti per sviluppatori, gli eventi e i dati (jquery data) associati al dom
  • Firefox:
    • AngScope
      Inspector degli scope associati al DOM. Richiede Firebug
    • Web Developer
      Lo stesso plugin presente anche su chrome.
    • Firequery
      Debugger per webapp con jQuery. Mostra anche gli eventi e i dati (jquery data). Richiede Firebug

martedì 27 settembre 2011

Tomcat e VisualVM

VisualVM è un'applicazione messa a disposizione nel Java Development Kit a partire dalla versione 6, update 7, e permette di monitorare tutte le applicazioni Java in esecuzione sul sistema.
L'applicazione non va installata e l'eseguibile si trova nella cartella bin della cartella di installazione JDK.
All'avvio, VisualVM mostra in automatico tutte le applicazioni che sono in esecuzione sul sistema, ma tramite alcune configurazioni, può anche monitorare JVM remote che abbiano porte aperte e accessibili tramite JMX.

Per farlo è sufficiente aggiungere alla configurazione di Tomcat dell'applicazione remota, le seguenti righe

-Dcom.sun.management.jmxremote.port=8086
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false


Dopo di che sarà necessario riavviare Tomcat e aggiungere una connessione JMX in VisualVM che punti alla porta 8086.



Per approfondire:
Monitoring Tomcat with Java VisualVM
VisualVM, troubleshooting per Java

venerdì 29 luglio 2011

ImageHyperlink



Magari può essere utile sapere che esiste un oggetto Hyperlink fatto apposta per le immagini. Esempio:

ImageHyperlink logsExcelExport = new ImageHyperlink(parent, SWT.CENTER);

Image image = ImageDescriptor.createFromURL(Platform.getBundle(AssessmentBaseErrorCodes.ASSESSMENT_CLIENT_BASE_PLUGIN_ID).getEntry("icons/action-savexls.png")).createImage();
logsExcelExport.setImage(image);
logsExcelExport.setLayoutData(GridDataFactory.swtDefaults().align(SWT.END, SWT.END).hint(17, SWT.FILL).create());
logsExcelExport.setToolTipText("Esporta in Excel");


Come dice il nome, genera un'immagine cliccabile.

lunedì 18 luglio 2011

Testing methods secured with Spring Security

Spring Security allows to secure access to methods, allowing execution only for user with defined roles.

For example, using annotation to configure the roles required:

public interface MyService
{

 @PreAuthorize("hasRole('USER') OR hasRole('ADMIN')")
 void hello();

 @PreAuthorize("hasRole('ADMIN')")
 void bye();

}

In order to call the bye() method the user must have the ADMIN role, for hello() method also the the USER role is enough.

If a secured method is called by a user without the needed roles is raised an exception of type org.springframework.security.access.AccessDeniedException.

Method security is active even during tests, so we have developed an annotation and a listener that can be used to setup easily user roles when testing (we use TestNG, probably something like this can be done also with Junit).

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface Authenticate {

 String username() default "";

 String[] roles() default {};
}

public class AuthenticationListener implements IInvokedMethodListener
{

 public static final String DEFAULT_USERNAME = "default";

 private static final String FAKE_PASSWORD = "fakePassword";

 /**
  * {@inheritDoc}
  */
 @Override
 public void beforeInvocation(IInvokedMethod method, ITestResult testResult)
 {
  if (method.isTestMethod())
  {
   ITestNGMethod testMethod = method.getTestMethod();
   Method javaMethod = testMethod.getMethod();
   Authenticate userAnnotation = javaMethod.getAnnotation(Authenticate.class);
   if (userAnnotation != null)
   {
    String username = userAnnotation.username();
    if (username == null || username.isEmpty())
    {
     username = DEFAULT_USERNAME;
    }
    String[] roles = userAnnotation.roles(); // role may be null/empty
    authenticateUser(username, roles);
   }
  }
 }

 private void authenticateUser(String username, String... roles)
 {
  Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>();
  if (roles != null)
  {
   for (String role : roles)
   {
    grantedAuthorities.add(new GrantedAuthorityImpl(role));
   }
  }
  UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, FAKE_PASSWORD,
   grantedAuthorities);
  SecurityContextHolder.getContext().setAuthentication(token);
 }

 /**
  * {@inheritDoc}
  */
 @Override
 public void afterInvocation(IInvokedMethod method, ITestResult testResult)
 {
  if (method.isTestMethod())
  {
   SecurityContextHolder.clearContext();
  }
 }

}

The Authenticate annotation allows to set the username and a list of roles that must be used when executing a test method, the AuthenticationListener take care to configure the authentication token before test execution and to reset the security context after execution.

This is an example of a test method that uses the Authenticate annotation:

@ContextConfiguration("classpath:META-INF/spring/applicationContext*.xml")
@Listeners(AuthenticationListener.class)
public class MyServiceTest extends AbstractTestNGSpringContextTests
{

 @Autowired
 private MyService myService;

 @Test
 @Authenticate(username = "pippo", roles = {"ADMIN" })
 public void testCallHelloAsAdmin()
 {
  myService.hello();
 }

 @Test
 @Authenticate(username = "pippo", roles = {"USER" })
 public void testCallHelloAsUser()
 {
  myService.hello();
 }

 @Test
 @Authenticate(username = "pippo", roles = {"ADMIN" })
 public void testCallByeAsAdmin()
 {
  myService.bye();
 }

 @Test(expectedExceptions = AccessDeniedException.class)
 @Authenticate(username = "pippo", roles = {"USER" })
 public void testCallByeAsUser()
 {
  myService.bye();
 }
}


See also:
The demo project on GitHub
Spring Security
TestNG Listeners
Annotations

martedì 12 luglio 2011

Liquibase migration for Spring Security tables

Spring security default implementation requires to access to a database in order to do its job.

Here is the liquibase migration file for creating these tables.

The changesets 1, 2 and 2a create tables for authentication and authorization.
Changesets 3, 3a, 4, 5, 6 and 6a create tables for domain object security (ACL).
Tha last changeset, 7, insert some data in tables (2 users wioht their roles).



This migration is customized for MySql database, enforces the InnoDB engine when creates tables, but should work also on other databases.

See also:
Spring Security
Security Database Schema
Liquibase