Showing posts with label jsf. Show all posts
Showing posts with label jsf. Show all posts

Sunday, August 17, 2014

TDD - Test Driven Development

Intro:


One method for coding stable code is TDD.

The basis of TDD is to write the test first, test it (and get an obvious fail) and then write the implementation.

Why would you do it this way?

First:
Because you implement the classes as a request-contract.

Second:
You have value full tests to-go

Third:
With these tests, if you refactor code hopefully your test will alert you for any breakage

My Story:

I started on a project (Java EE 7 with JSF) and wanted to practice junit tests. But for Injected beans and Jsf-contexts, the story got tricky.

Now the Great test framework Arquillian has all the answers for that, BUT some of the things you need is only in alpha state. I struggled with it a lot. So much I actually choose not to do any tests...

BIG MISTAKE!

So when I tried to code a function for deleting a certain thing from the database (in the middle of relations) i got some problems. Every time I changed the code, I had to log in, navigate to the right site, try the function and then try to understand the giant EE stacktrace.

So I did a GIANT Refactoring (actually starting a new project and just copying in the entities).

I tried for 2 days to implement all of Arquillians might for testing actual websites in the server (Graphene, Selenium, Drone). But in the end it didn't work.

But I got the junit tests (run by Arquillian) to work (as injected beans).
So now I could actually test the beans function without all the login and stuff.

And when it's all implemented I can actually do manual Selenium tests to see that it actually works in the website.

A bonus thing is that the test wipes and then populates the database with test-data.
So if I have to drop the database (ex if I change the persistance classes) I don't have to create all the test data manually.

Summary:

So what can we (and especially I) learn from this?

Even if you don't do the tests first like TDD, have a test framework! It saves so much time.

Code ahoy!

Saturday, May 3, 2014

JSF 2.2 FileUpload and a way to get it back

So my Web app needed to be able to upload images for users, "connect" the user and the image and to be able to actually show the image.


Upload:

So JSF 2.2 has a really simple way of doing this. You just put <h:inputFile /> and connect this to a Bean. The type should be "Part" (javax.servlet.http.Part). But to remember is that the <h:form> needs too add enctype="multipart/form-data" as an attribute, <h:form enctype="multipart/form-data">.

Connect:

So now we have a Part in the Bean, but how to save it and where?
Some may want to save the image in the database, this can be done with the BLOB-type. you then have to get the input stream and read it as bytes.

Pros:
All in one place, handled by the DBMS.

Cons:
Database takes much more space
Harder to export all the data for backup-solutions

So what do we do then?
We can save it on the hard drive as regular files. A risk is if the file contains a virus.
How we actually save this is rather easy. The Part-class has a "write"-method which you either can give a relative path or a absolute path. The relative path may put it in the web-applications tmp-folder, it's really the server who controls where its put.

The absolute path makes it easy to do backup scripts to make backups. The big problem is how to reach the files from the web app.

Path:

How to reach files from "above" the web-apps folder is different for the servers. Glassfish has Virtual host/server. Some has context-properties.

The one I have focused on is Wildfly (JBoss Application Server 8).
It was a bit tricky to find the right answer.

But in the config file for your server (domain.conf or one of the standalone confs) there is a subsystem for undertow. Undertow is the new servlet container for JBoss.

In that subsystem there is two parts that's interesting for us right now: Host and Handlers.


In the Handlers part we add
<file name="images-handler" path="your/path/to/save"/>

you can use your servers path-variables

and in the Host part
<location name="/images" handler="images-handler"/>

The handler takes care of where the folder will be retrieved from (read from) and the Host will controll how the web-app will reference it.
In this case you reach it by http://serveradress:port/images

Display:

Now comes the last tricky part. The images-folder is reachable now BUT is reachable by the server-adress WITHOUT the web-apps adress on top of it. You can probably map it to be reachable.

So <graphicImage> gets problems due to it being relative to the web-app.
A simple <img> works great thou.


So either find a way to map it better or use a regular <img>


So that's it for the simple fileUpload of images, especially with Wildfly.

Code ahoy!

Monday, April 14, 2014

JPA: Hibernate Implementation "lazily initialize a collection"

Today I have struggled half a day with a frustrating problem.

I have a ManyToMany-relationship (JPA) with two Entities. Shop and Brand, it's also bidirectional.

Hibernate and Spring-veterans sees where I'm going with this...

If I want to get a Object of Shop from the database, everythings simple. But if I want to get the attribute that's the "ManyToMany" (in this case "Brand") I would get it as a form of Collection.

But here's the kicker: Hibernate has a lazy initialization of these kinds of collections. This is for saving a lot of data loading for every time you get a Shop-object from the database.

I wanted to have a JSF-form with my data and the possibility to update it (specifically the Brands). I wanted to use the selectManyCheckBox component in JSF.

So the Hell began here.

The specific exception I got was (I also got the role-error earlier):
javax.servlet.ServletException: failed to lazily initialize a collection, could not initialize proxy - no Session

You can set the annotation of the ManyToMany to suggest "EARLY" so that it loads all the collection-data with the regular.

And that solution didn't solve my problems. It feels like I almost tried every solution known to man to solve this problem. I did beans that sole purpose was to get the Brands as a list from the Shop and try to merge it with the data in the form and the update-bean.

Of course I tried to google solutions. 95% of the links led me to thinking it was the classic lazy-problem that the Hibernate-session closed before I got my collection data.

But something wasn't right. Because I actually got the data to show in the form correctly quite early. It was the update that caused the problem.

The update was a bean that held the data from the JSF-component, they were connected.
But why did a lazy-error show when it wasn't supposed to load the data but actually update it?

I tried View filter (Open View in Session-pattern), I tried Stateful beans with EXTEND persistance unit.


After half a day I stumble to Hatim Alimam's blog were he had the same problem (but with Primeface implementation).
http://blog.hatemalimam.com/hibernate-lazyinitializationexception-and-pselectcheckboxmenu/

It was a little <f:attribute> that was needed!
If I just put   <f:attribute name="collectionType" value="java.util.ArrayList" /> in the <f:selectManyCheckBox>    Everything worked!

So it wasn't really the classic Lazy-problem, but with that Exception-message, one might think so...

So I hope anyone that has the same problem I had either stumble to this blog or Hatim's.

Cheers!

Sunday, April 13, 2014

Wildfly Injection and JPA: troublesome

So I've been making a Webapplication with classic CRUD via JPA. The database is also used for login-functions. I use JSF with Facelets for View.

JSF can manage beans easily e.g (value="#{myBean.value}")

So I thought that the Bean could be a @Entity. I even have a book that use it like that.
I then Inject the bean in my Facade (a DAO) that should persist it.

I checked so that it had the values that I gave from the View (JSF-form).


But here's the kicker!

I get "java.lang.IllegalArgumentException: Unknown entity: myclass#$Proxy$_$$_WeldClientProxy".

I tried of writing the classes manually in the persistance.xml without any luck.

After a lot of digging, I learned that the Bean that Weld injects (I use Wildfly-server that uses Weld) you doesn't actually get a real instance of your bean. You get a Proxy. So I could get the values, but it was not seen as an Entity.

I confirmed this by making a manual instance of the bean and persisting it with the same Facade-code.

The only difference was the Injection.

So my solution was to make a controller bean which had a manually created field of the bean. And use that bean e.g (value="controllerBean.myBean.value")

The controller bean then used the Facade for persistance.

This solution works for me, the controller bean can then do some validation and more.

Fine and dandy!