Simple REST WS in Java
It's really simple to do REST Webservices using JavaEE 6. Create an class that extends Application with an ApplicationPath annotation:
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; @ApplicationPath("rest") public class ApplicationConfig extends Application { }
Then, use proper annotations to publish your REST services:
import javax.ws.rs.FormParam; import javax.ws.rs.Path; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @Path("test") public class TestREST { @GET @Produces("application/xml") public Result noParms() { return new Result(1, "OK"); } @GET @Path("/{p}") @Produces("application/xml") public Result oneParameter( @PathParam("p") String parm) { return new Result(1, "Hi, " + parm); } @POST @Produces("application/xml") public Result twoParms( @FormParam("n") String name, @FormParam("s") String sname) { return new Result(2, sname + ", " + name); } }
Invoke with simple GET request (like "http://server/myapp/rest/test/Bro") or an HTML POST form. "Result" is a simple POJO with JAXB annotations.
NB-managed JDBC connections
If you are developing a NetBeans-based module or application and need a database connection, you can use "Database Explorer API" to manage them for you. Geertjan has the recipe, but there are two catchs:
- DatabaseConnection.getJDBCConnection(true) must NOT be called on EDT;
- ConnectionManager.showConnectionDialog MUST be called on EDT.
So, if you want to do something like this:
DatabaseConnection dbc = ConnectionManager .getDefault() .getConnection(databaseConnectionName); ConnectionManager.getDefault() .showConnectionDialog(dbc); Connection conn = dbc.getJDBCConnection(true);
You must call line 4 on EDT and line 6 on a RequestProcessor or similar. I had to deal with these scenarios:
- Populate a JComboBox on a button's click event: I created a RP with the sixth line plus statements and result sets - first and forth line are called by Swing on EDT;
- Populate an asynchronous ChildFactory: my code is called on CF's refresh thread. I had to encapsulate showConnectionFactory on EDT using SwingUtilities.invokeAndWait, without using RP for line 6.
It's strange at first, but works nice (way better than developing my own database connection management).
BTW, if you call DatabaseConnection.getJDBCConnection on EDT you receive an useful warning, but you will suffer if you forget to call ConnectionManager.showConnectionDialog on EDT (no cool warnings to help you). I filled a request for adding this warning in bug 188741.
Using NetBeans Parser API with Navigator API
So, you created a new language on you NBP-based application and associated it with a new file type. Now, you need to show your parse result on your Navigator panel. I haven't found a standard way to do so, but the best shot so far was adding the parser result to the DataObject's CookieSet. This way you can lookup it in your NavigationPanel's panelActivated. Easy and fast.
sed-like function in scala
It was a long time without using Scala, but I had a problem that it solved like a charm. I need to edit a huge file with one XML per line, replacing "b" for "b
def solveMyProblem = { import java.io.File import scala.io.Source Source.fromFile(new File("path-to-file")) .getLines() .map { _.replaceAll("(<a>(.*)</a>)", "$1<c>$2</c>"); } .foreach { Console.println(_) } }
I'm still using Scala 2.7, but this got my problem solved. It was easy to test - instead of thousands of lines on my Console, I put a ".take(10)" and I got something like Linux's "sed | head".
BTW, I guess it could be improved even more, but I don't have time to do that too.
Using NewType on a NetBeans Node
Given any Node on a NetBeans Platform Application, you can create a "new action" by adding "SystemAction.get(NewAction.class)" to your node's actions (overriding Node.getAction). You must also override the Node.getNewTypes.
Everything is simple and obvious - except one detail: be careful when overriding the node's lookup. This works:
public class MyNode extends AbstractNode { public MyNode() { super(Children.LEAF); } }
But this don't (you will only get a grayed "Add" menu):
public class MyNode extends AbstractNode { public MyNode(MyElement a) { super(Children.LEAF, Lookups.fixed(a)); } }
The answer is not obvious (I took hours to find out) - you must add "this" to the node lookup, using the old InstanceContent recipe:
public class MyNode extends AbstractNode { public MyNode(MyElement a) { this(a, new InstanceContent()); } public MyNode(MyElement a, InstanceContent ic) { super(Children.LEAF, new AbstractLookup(ic)); ic.add(this); ic.add(a); } }
Mixing JPA with JAXB/JAXWS
With JavaEE 6, you can publish an SOAP WebService as easy as 1-2-3. It mixes well with JPA, but I give you a small advice: if you need bidirectional ORM mappings, one of them MUST be @XmlTransient. Otherwise, you will receive a com.sun.xml.ws.streaming.XMLStreamReaderException ("unexpected XML tag. expected: {yourns}yourtag but found: {http://schemas.xmlsoap.org/soap/envelope/}Envelope").
h:selectManyCheckbox with multiple columns/rows
If you ever tried to use the
Let's talk about a feature of the
Pretty nice, but the items are rendered with the group orientation: this means JSF will render an horizontal table for the groups with nested horizontal tables for the items. Still ugly!
You can solve this using Tomahawk, but I think it's too much trouble only to get this simple requirement. I prefer using a pure-JSF solution like a new Renderer. Mojarra's renderer makes this job very easy:
public class MyRenderer extends SelectManyCheckboxListRenderer { // keeps track of current rendering private boolean inner; // overriding with synchronized @Override public synchronized void encodeEnd( FacesContext context, UIComponent component) throws IOException { super.encodeEnd(context, component); } @Override protected void renderBeginText( UIComponent component, int border, boolean alignVertical, FacesContext context, boolean outerTable) throws IOException { // are we at the inner table? this.inner = !outerTable; super.renderBeginText(component, border, alignVertical ^ inner, context, outerTable); } @Override protected void renderEndText( UIComponent component, boolean alignVertical, FacesContext context) throws IOException { super.renderEndText(component, alignVertical ^ inner, context); // reset after inner table is rendered this.inner = false; } @Override protected void renderOption( FacesContext context, UIComponent component, Converter converter, SelectItem curItem, Object currentSelections, Object[] submittedValues, boolean alignVertical, int itemNumber, OptionComponentInfo optionInfo) throws IOException { super.renderOption(context, component, converter, curItem, currentSelections, submittedValues, alignVertical ^ inner, itemNumber, optionInfo); } }
The trick is pass "alignVertical" parameter XOR inner state. This will change the alignment for the inner table. If you use "pageDirection" as layout, the inner table will use "lineDirection" and vice-versa. Using the "roles" example, the groups will be aligned horizontally and their roles, vertically.
Now, if you don't want to use groups, you can still benefit - create pseudo-groups for each N elements. This will give you a matrix-like checkbox list.
Using f:selectItems with JPA entities
It's a common scenario: you must do a "SELECT e FROM Entity e" with JPA and pass it to a <h:selectOneMenu> or a <h:selectManyList>. Unfortunately, if you google it, you will find a lot of strange solutions.
I've tested a simple solution on JavaEE 6. On my managed bean, I can define a property like this:
... public class MyBean { ... @PersistenceContext private EntityManager em; public Converter getConverter() { return new Converter() { @Override public Object getAsObject( FacesContext fc, UIComponent uic, String string) { return (string == null) ? null : em.find(MyEntity.class, Long.parseLong(string)); } @Override public String getAsString( FacesContext fc, UIComponent uic, Object o) { return (o == null) ? null : Long.toString(((MyEntity) o).getId()); } }; } }
According to JSF specification, only managed beans can be injected. This is why I declared it as an inner class.
This way, the converter allows you to work only with entities, instead of manually storing IDs on the managed bean. This means the page can bind to this property when a conversion is needed:
<h:selectOneMenu value="#{myBean.myEntitySelection}"> <f:selectItems value="#{myBean.myEntityList}"/> <f:converter binding="#{myBean.converter}"/> </h:selectOneMenu>
One last step: your Entity must have an working "equals" method. If you forget this, you will receive the message "Validation Exception: Value is invalid".
Usually, a boilerplate, like this one generated by NetBeans will suffice:
@Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final MyEntity other = (MyEntity) obj; if (this.id != other.id && (this.id == null || !this.id.equals(other.id))) { return false; } return true; }
Works like a charm on JSF 2, but I haven't tested on JSF 1.2.
BTW, this solution can be refactored to became a more generic: create a base entity class that declares a "getId" method returning Serializable. Then, the converter can be a class receiving an entity manager and the persistent class.
Unit Testing EJBs 3.1 with Glassfish Embedded
Pretty simple, indeed. You need the "glassfish-embedded-all-3.0-b74b.jar", and use the new EJBContainer like this:
MyBean ejb = (MyBean) EJBContainer .createEJBContainer() .getContext() .lookup("java:global/classes/MyBean"); assertEquals(3, ejb.add(1, 2));
And remember that you can use a deployment descriptor on your test classpath to customize both transaction and datasource for your unit testing.
If you are using maven, use this dependency instead of javaee-api:
<dependency> <groupId>org.glassfish.extras</groupId> <artifactId>glassfish-embedded-all</artifactId> <version>3.0-b74b</version> <scope>provided</scope> </dependency>
If you put "javaee-api" as "provided" and GF as "test", you will receive nasty "Abscent Code" errors.
Conversational Scope on JSF 2.0 (without Custom Scope)
JSF 2.0 is finally out. One thing that you will notice is the absence of a "conversational" scope. That would solve a lot of problems I have, but, unfortunately, I must wait for the next release. Or not?
There's no silver bullet to solve it, but I found a simple workaround using "view" scoped beans. Works for most cases - unless you need redirection or other advanced requirements.
First, your "conversational" managed bean must be have a "view" scope:
@ManagedBean(name="tbean") @ViewScoped public class TBean { private String name; private String result; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getResult() { return result; } public String sayHi() { result = "Hi, " + name; return ""; } }
No big deal: just a POJO with @ViewScoped. The catch is you must return empty on your action. The view is simple, too:
<h:body> <h:form rendered="#{empty tbean.result}"> Name: <h:inputText value="#{tbean.name}"/> <h:commandButton value="hi!" action="#{tbean.sayHi}"/> </h:form> <h:panelGroup rendered="#{not empty tbean.result}"> <h1><h:outputText value="#{tbean.result}"/></h1> <h:button value="back" outcome="index"/> </h:panelGroup> </h:body>
Nothing really new: classic JSF 1.0 magic tricks with the rendered attribute. The real catch, although, is the view scope. The bean will remain as long as you keep the current view (by returning empty on your actions). The "back" button clears the form and conditionally rendered components will give the feel of different pages.
This means you can easily have an three-page CRUD (list, view, edit), or an wizard-style page, that will reset when you enter it and keep state as long as you stay on "subpages".
Your page will grow fast using this method, but, since Facelets support is now native, you can use