VOOZH about

URL: https://www.javacodegeeks.com/2014/11/testing-secured-ejbs-with-arquillian.html

⇱ Testing secured EJBs with Arquillian


Testing secured EJBs has been historically hard to get right. Up until now, I have been using proprietary techniques like JBossLoginContextFactory described in the article Testing secured EJBs on WildFly 8.1.x with Arquillian to test secured EJBs.

During this year Devoxx, David Blevins, founder of the Apache TomEE project – a lightweight Java EE Application Server, brought to my knowledge a little trick we can use to deal with Java EE security in a standard way that works across all Java EE compliant servers.

The example used in this post is available at javaee-testing/security on GitHub.
 

The code

The code to test includes an entity and an EJB service as follows.

Book Entity

@Entity
public class Book {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Integer id;
 private String isbn;
 private String title;

 public Book() {
 }

 public Book(String isbn, String title) {
 this.isbn = isbn;
 this.title = title;
 }

 // getters and setters omitted for brevity
}

Bookshelf EJB Service

@Stateless
public class BookshelfService {

 @PersistenceContext(unitName = "bookshelfManager")
 private EntityManager entityManager;

 @RolesAllowed({ "User", "Manager" })
 public void addBook(Book book) {
 entityManager.persist(book);
 }

 @RolesAllowed({ "Manager" })
 public void deleteBook(Book book) {
 entityManager.remove(book);
 }

 @PermitAll
 @TransactionAttribute(TransactionAttributeType.SUPPORTS)
 public List<Book> getBooks() {
 TypedQuery<Book> query = entityManager.createQuery("SELECT b from Book as b", Book.class);
 return query.getResultList();
 }
}

The test class uses Arquillian for the integration tests and asserts that the security roles defined on our EJB are respected.

Bookshelf Service Tests

@RunWith(Arquillian.class)
public class BookshelfServiceIT {

 @Inject
 private BookshelfService bookshelfService;
 @Inject
 private BookshelfManager manager;
 @Inject
 private BookshelfUser user;

 @Deployment
 public static JavaArchive createDeployment() throws IOException {
 return ShrinkWrap.create(JavaArchive.class, "javaee-testing-security.jar")
 .addClasses(Book.class, BookshelfService.class, BookshelfManager.class, BookshelfUser.class)
 .addAsManifestResource("META-INF/persistence.xml", "persistence.xml")
 .addAsManifestResource(EmptyAsset.INSTANCE, ArchivePaths.create("beans.xml"));
 }

 @Test
 public void testAsManager() throws Exception {
 manager.call(new Callable<Book>() {
 @Override
 public Book call() throws Exception {
 bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
 bookshelfService.addBook(new Book("978-1-4493-2829-0", "Continuous Enterprise Development in Java"));

 List<Book> books = bookshelfService.getBooks();
 Assert.assertEquals("List.size()", 2, books.size());

 for (Book book : books) {
 bookshelfService.deleteBook(book);
 }

 Assert.assertEquals("BookshelfService.getBooks()", 0, bookshelfService.getBooks().size());
 return null;
 }
 });
 }

 @Test
 public void testAsUser() throws Exception {
 user.call(new Callable<Book>() {
 @Override
 public Book call() throws Exception {
 bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
 bookshelfService.addBook(new Book("978-1-4493-2829-0", "Continuous Enterprise Development in Java"));

 List<Book> books = bookshelfService.getBooks();
 Assert.assertEquals("List.size()", 2, books.size());

 for (Book book : books) {
 try {
 bookshelfService.deleteBook(book);
 Assert.fail("Users should not be allowed to delete");
 } catch (EJBAccessException e) {
 // Good, users cannot delete things
 }
 }

 // The list should not be empty
 Assert.assertEquals("BookshelfService.getBooks()", 2, bookshelfService.getBooks().size());
 return null;
 }
 });
 }

 @Test
 public void testUnauthenticated() throws Exception {
 try {
 bookshelfService.addBook(new Book("978-1-4302-4626-8", "Beginning Java EE 7"));
 Assert.fail("Unauthenticated users should not be able to add books");
 } catch (EJBAccessException e) {
 // Good, unauthenticated users cannot add things
 }

 try {
 bookshelfService.deleteBook(null);
 Assert.fail("Unauthenticated users should not be allowed to delete");
 } catch (EJBAccessException e) {
 // Good, unauthenticated users cannot delete things
 }

 try {
 // Read access should be allowed
 List<Book> books = bookshelfService.getBooks();
 Assert.assertEquals("BookshelfService.getBooks()", 0, books.size());
 } catch (EJBAccessException e) {
 Assert.fail("Read access should be allowed");
 }
 }
}

The trick is on two helper EJBs which allow our test code to execute in the desired security scope by using the @RunAs standard annotation.

Bookshelf Manager role

@Stateless
@RunAs("Manager")
@PermitAll
public class BookshelfManager {
 public <V> V call(Callable<V> callable) throws Exception {
 return callable.call();
 }
}

Bookshelf User role

@Stateless
@RunAs("User")
@PermitAll
public class BookshelfUser {
 public <V> V call(Callable<V> callable) throws Exception {
 return callable.call();
 }
}

Running

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running com.samaxes.javaeetesting.security.BookshelfServiceIT
nov 23, 2014 2:44:48 AM org.xnio.Xnio <clinit>
INFO: XNIO version 3.2.0.Beta4
nov 23, 2014 2:44:48 AM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.2.0.Beta4
nov 23, 2014 2:44:49 AM org.jboss.remoting3.EndpointImpl <clinit>
INFO: JBoss Remoting version (unknown)
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 36.69 sec - in com.samaxes.javaeetesting.security.BookshelfServiceIT

Results :

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0

Happy tests!

Reference: Testing secured EJBs with Arquillian from our JCG partner Samuel Santos at the Samaxes blog.
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

πŸ‘ Photo of Samuel Santos
Samuel Santos
November 28th, 2014Last Updated: November 28th, 2014
0 96 3 minutes read

Samuel Santos

Java and Open Source evangelist, JUG leader and Web advocate for web standards and semantic technologies.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz