Past few months, I've been working with Angular 2. I didn't pick it, rather been forced to. In a good sense. We use it as UI tech for Red Hat Migration Toolkit, AKA project Windup - for it's web UI. I was pushing my (still) favorite Apache Wicket, which, by the way, is picking up Java 8 goodies to make UI coding even greater pleasure. I even created a PoC UI for managing the apps, with JPA 2 and all. But someone else, much more senior than me, was pushing Angular 2, which at that time was .alpha1 or so. It was very clear to me that learning this ball of craziness glued together by a dozen of libraries, frameworks, hacks and tools, will take loooong time. And it does. But I told to myself - f it, let's see how crazy things can get. And let's add that to my skill set. If I will learn this, then I will learn anything. And I gave up pushing Wicket, with which I believe we would be a bit further in web UI features (but that's highly speculative).
Now what. I am still learning it all, as it has many, many dark corners. I came from Java world, and I was shocked by the chaos in JavaScript world. Nothing is for sure, there's lack of documentation, integration often breaks, micro versions break compatibility, there's little you can rely on - typically, only the top few libraries are well tested, documented, and maintain backward compatibility. On the bright side, the development pace is impressive. But to what end? To me, it seems that the whole ecosystem recipitantly, wildly, yet slowly, is getting closer to what mature development platforms have for years or decades. That's true for all aspects: Dependencies management, centralized repository, syntax, OOP, reflection, debugging, logging, UI templates, expression language, exception handling, ... but this doesn't happen following a plan. There are no specifications, no drafts. The common ground is basically only EcmaScript, or better said, what the browsers that majority of people have, implement.
Fun fact: My bachelor's thesis back in 2004 was about contemporary JavaScript, showing how cool language that actually is, how it can emulate classes, and how it can be used for complex applications. To prove that, I programmed a cover of Harrel W. Stilles' Miner VGA game for DOS, a basic Turing machine emulator, and an implementation of a neural network with backpropagation, simulated annealing and that AI stuff. In short, JavaScript was my beloved toy language. I'm not saying it's not now, just what has grown around it now, most of all, reminds me this:
Anyway - this series (if it becomes a series, that is) won't be about complaints, rather the landmines I've stepped on with a spectacular few-hours flight through the air of console.log()-based debugging and deciphering the Angular stacktraces (which are useless most of the time as they only contain references to Zone.js).
I don't want to complain all the time to my team how Angular2 or other JS thing hurt me today, so I'll drop my daily frustration here. Maybe someone will find it interesting, funny or even usable - in which case, good for you
I've digged another tiny tool I wrote in the past. This time it's CSV Cruncher.
This tool takes a few .csv files and turns them into SQL tables.
Then you can query the data and export another CSV.
This gives you all the power of SQL, if you consider you can use all the tricks like self-joins, recursive selects, triggers, stored procedures. It uses HyperSQL.
You write `ide.sh FooBar` and it most likely opens what you are looking for:
1) Tries to open the path.
2) If it doesn't exist, it tries to open that file anywhere in the directory tree (provided it has some of the file name suffixes I currently use).
3) If not exists, it opens the files that contains a type of that name (class, function, interface).
4) If not found, it opens the files that contain given pattern.
This blog's source WYSIWYG is buggy so it's hard to edit, the up-to-date version is at gist.
#!/bin/bash
set -x
NB="/sw/prog/netbeans/8.2/bin/netbeans"
MAX_FILES_TO_OPEN=5
## If the argument is a path to a file, open it.
if [ -f "$1" ] ; then
"$NB" "$1"
## Else if it's a path in a form of foo*bar (contains a star), open all that match, of types .java, .ts, .html, .xml, .ftl
elif expr "$1" : ".*\*.*" ; then
find . -path "./*/target/*" -prune -o \( -name "*$1*".java -o -name "*$1*".ts -o -name "*$1*".html -o -name "*$1*".xml -o -name "*$1*".ftl \) -print | xargs $NB
## Else if there's a TypeScript class of that name, open it.
git grep -q -E "(class|function) +$1"
elif [ $? ] ; then
git grep -l -E "(class|function) +$1" | head -n $MAX_FILES_TO_OPEN | xargs "$NB"
## Else open whatever matches the given pattern.
else
COUNT=`git grep -l "$1" | wc -l`
if [[ "$COUNT" -gt "$MAX_FILES_TO_OPEN" ]] ; then echo "Too many `git grep` matches, taking first $MAX_FILES_TO_OPEN."; fi
git grep -l "$1" | head -n $MAX_FILES_TO_OPEN | xargs "$NB"
fi
Compiler level properties still not there, what a disappointment. They might be in JDK 11, hopefully. This whole story reminds me how Czech highways are being built.
Windup 3.0 will be a web application. It can still be used as command line application, but on top of that, you can deploy Windup to a JBoss WildFly (or EAP) and scan your applications from a nice web UI.
From the developers perspective, the frontend stack is Angular 2, TypeScript, ReactJS, Keycloak for security, and few other libraries. It's a bit pain for me to learn the new paradigm and to leave the very comfortable Java ecosystem, but on the other hand, looks like all the JavaScript-centered craziness is going to stay around for a couple of decades and eventually settle down, so why not embrace it (thinking, "Banzaaaii!!" )
When coding against Titan graph database, you may encounter the exception below.
In our case, we are using Tinkerpop Frames, and one frame was using the same value for an edge label as other for a property.
@Adjacency(label="project")
...
@Property("project")
...
To fix that, simply use different values.
Caused by: java.lang.IllegalArgumentException: Querying for edges but including a property key: project
at com.thinkaurelius.titan.graphdb.query.vertex.BasicVertexCentricQueryBuilder.constructQuery(BasicVertexCentricQueryBuilder.java:428)
at com.thinkaurelius.titan.graphdb.query.vertex.VertexCentricQueryBuilder.execute(VertexCentricQueryBuilder.java:62)
at com.thinkaurelius.titan.graphdb.query.vertex.VertexCentricQueryBuilder.titanEdges(VertexCentricQueryBuilder.java:79)
at com.thinkaurelius.titan.graphdb.query.vertex.VertexCentricQueryBuilder.edges(VertexCentricQueryBuilder.java:98)
at com.thinkaurelius.titan.graphdb.vertices.AbstractVertex.getEdges(AbstractVertex.java:184)
at com.tinkerpop.blueprints.util.wrappers.event.EventVertex.getEdges(EventVertex.java:21)
at com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler.removeEdges(AdjacencyAnnotationHandler.java:100)
at com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler.processVertex(AdjacencyAnnotationHandler.java:67)
at com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler.processElement(AdjacencyAnnotationHandler.java:26)
at com.tinkerpop.frames.annotations.AdjacencyAnnotationHandler.processElement(AdjacencyAnnotationHandler.java:15)
at com.tinkerpop.frames.FramedElement.invoke(FramedElement.java:140)
at com.sun.proxy.$Proxy111.setProject(Unknown Source)
The main addition is the rules for EAP 5 to EAP 7 rules.
Use the --target eap:7 parameter to use them.
Thanks Marek for all the hard work and all who contributed the knowledge.
Enjoy!
PS: There's one little, tiny, bug which was not found until a live demo, so if you hit that, please wait for next release or fix with the jar in the attachment.
On Friday, Windup 2.6.0.Final was released. Download at the Windup website.
There are 2 particular things to highlight:
Mavenization.
Windup 2.6 can create a basic Maven project structure for your application. When you execute Windup with the --mavenize flag, Windup analyzes the structure of your application and creates POM files with the appropriate dependencies for each of your application modules.
Shared archives
If a big application contains same libraries or modules multiple times appear in multiple places in your input applications, and adjusts incident counts and effort estimates to avoid double-counting. If you analyze multiple applications together, Windup bundles information about the shared archives to present you with information on the common libraries shared across your applications.
When you validate a XML file, and this has a XSD URL for some namespace, and this XSD URL redirects to another URL, then the default EntityResolver2 takes that as a failure.
Jess noticed (and fixed) this when debugging WINDUP-997.
So for instance, this XML was not valid, because some of the URLs (perhaps in the linked XSD's) is behind a redirect:
So here's a fixed implementation. It follows only a single redirect, but change the if to a for and it will follow more (don't forget to prevent infinite loop).
package org.jboss.windup.rules.apps.xml.xml;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.ext.EntityResolver2;
/**
* This is an {@link EntityResolver2} that has been enhanced to support URL redirection.
*
* @author <a href="mailto:jesse.sightler@gmail.com">Jesse Sightler</a>
*/
public class EnhancedEntityResolver2 implements EntityResolver2
{
@Override
public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException
{
return null;
}
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException
{
return resolveEntity(null, publicId, null, systemId);
}
@Override
public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId) throws SAXException, IOException
{
URL url = baseURI != null ? new URL(new URL(baseURI), systemId) : new URL(systemId);
URLConnection connection = url.openConnection();
// Not a HTTP connection... skip redirection logic
if (!(connection instanceof HttpURLConnection))
return new InputSource(connection.getInputStream());
HttpURLConnection httpConnection = (HttpURLConnection)connection;
int status = httpConnection.getResponseCode();
if ((status != HttpURLConnection.HTTP_OK) &&
(status == HttpURLConnection.HTTP_MOVED_TEMP
|| status == HttpURLConnection.HTTP_MOVED_PERM
|| status == HttpURLConnection.HTTP_SEE_OTHER))
{
String newUrl = httpConnection.getHeaderField("Location");
httpConnection = (HttpURLConnection) new URL(newUrl).openConnection();
}
InputSource inputSource = new InputSource(httpConnection.getInputStream());
inputSource.setSystemId(url.toString());
inputSource.setPublicId(publicId);
return inputSource;
}
}
In real life scenarios, if a company has multiple .ear applications, it's very likely that they will bundle various subcomponents, for instence, EJB jars with EJB's used across the company.
In Windup 2.4.0, we added the ability to analyze multiple applications. But that didn't count with the fact stated above. That lead to these re-used submodules being counted multiple times in the migration effort and total incidents sums, which doesn't reflect the real amount of effort - once the submodule is done, it's done for all applications.
So since Windup 2.6.0, this behavior is corrected. If Windup spots some libraries which are used multple times, it will create a "virtual" application in the report, called "<shared-libs>" and 1) report it only once, 2) analyze it only once (the other copies of the same jar won't be re-scanned).