Angular 6 and RxJS: Multiple API Calls Simultaneously

Angular 6 and RxJS are fantastic tools for developing single page web applications. In Angular 6, a problem we often face, is multiple components require some set of shared data. Sure, we could copy and paste the individual service calls, but that’s not the best approach. We should really be trying to centralize shared data requests.

First, we need to make a wrapper object to encapsulate the requested data:

export interface IDataCollection {
    data?: IApiResponse<Data[]>;
    secondData?: IApiResponse<SecondData[]>;
}

The next thing to do is make the request function:

/** Static for example simplicity **/
export class DataCollectionService {
    public static getDataCollection(dataService: DataService): Observable<IDataCollection> {
        return Observable.forkJoin(
            dataService.getData(),
            dataService.getSecondData(),
        ).map(response => {
                let dataCollection = {
                    data: response[0],
                    secondData: response[1]
                 } as IDataCollection;
                 // More logic goes here.

                 return dataCollection;
            }
        );
    }
}

Now, all you need to do is subscribe to the observable:

DataCollectionService.getDropdownCollection(this.dataService).subscribe(
            (dataCollection: IDataCollection) => {
                this.data = dataCollection.data;
                this.secondData = dataCollection.secondData;
                // More logic goes here.

            },
            // Should be global error handler in your app.
            (err: any) => console.log(err),
            // Should be your logging framework here
            () => "Retrieved data for dropdown boxes."
);

That’s it! You’ve combined multiple service calls into one concise function.

Let me know if this worked for you.

.NET: Easily Install Log4Net in .NET Web Application

Logging is an integral tool for debugging applications. For newer developers, or developers who don’t typically work in the .NET ecosystem, setting up Log4Net can be confusing and complicated.

First, we need to add Log4Net to our application with NuGet. Navigate to the top of Visual Studio and click:

 "Tools > NuGet Package Manager > Manage NuGet Packages for Solution" 

Next, in the search bar, type “Log4Net” and install the package to your project.

Open up your AssemblyInfo.cs file and add:

 [assembly: log4net.Config.XmlConfigurator(ConfigFile = "config.log4net", Watch = true)] 

Under your project’s directory, create a “config.log4net” file. This file is customizable but for today, we’re going to stick with a simple configuration that outputs to Visual Studio’s “Output” window and writes to a log file located in your project’s directory. Here’s the file content:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <log4net>
    <!-- Need trace for web applications. -->
    <appender name="TraceAppender" type="log4net.Appender.TraceAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p %c %m%n"/>
      &lt;/layout>
    </appender>

    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="your-app-logs.txt" />
      <appendToFile value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>

    <root>
      <level value="ALL"/>
      <appender-ref ref="TraceAppender"/>
      <appender-ref ref="FileAppender"/>
    </root>
  </log4net>
</configuration>

Now, add your logging code like so:

class ClassNeedsLogging {
        private static readonly ILog Logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

        public void MethodThatNeedsLogging() {
            Logger.Info("Hit MethodThatNeedsLogging");
        }
}

That’s it. Now, you should see logging in the Visual Studio “Output” window. You’ll also be able to see logging in “{Your Project Directory}/your-app-logs.txt”.

.NET Error: Could Not Load File or Assembly “System.Runtime, Version=X.X.X.X, Culture = neutral …” or One of Its Dependencies.

This will be a rather short post today guys. This caused a big headache for me so I just want to get it out there.

I ran into this error: ‘Could Not Load File or Assembly “System.Runtime, Version=X.X.X.X, Culture = neutral …” or One of Its Dependencies’

I googled the heck out of it. Tried multiple different things including repairing visual studio, messing with config files, and much more.

None of the suggested solutions worked. I ended up having to delete the ‘bin’ and ‘obj’ folders.

An old DLL may have been causing some issues. Either way, this fixed it.

Have fun coders. Let me know if this fixed your issue.

-Steve

VideoJS Error: VideoJS showing HTML5 video player with AngularJS

Recently, I was trying to integrate VideoJS into a personal project. I followed the getting started guide located at http://videojs.com/getting-started/ to no avail.

If this works for you, great! But if you are getting the standard HTML5 video player, try to instantiate VideoJS via JavaScript. In your angular controller, add this:

        var video;
        $scope.$on('$destroy', function () {
            // Destroy the object if it exists
            if ((video !== undefined) && (video !== null)) {
                video.dispose();
            }
        });
  
        // Where my-video-id is the id in the video tag from the getting started guide
        videojs("my-video-id").ready(function () {
            video = this;
            // Replace $scope.video.url with your video url
            // Replace $scope.videos.type with your video type, for example, 'video/mp4'
            video.src({src: $scope.videos.url, type: $scope.videos.type});
        });

I’ve seen this recommended for when the video “is only loaded on hard refresh”. For me, the standard HTML5 video player was always showing, even when hard refreshing the page. Adding the above code caused the VideoJS player to load instead of the standard HTML5 player.

That’s it! You should be using the VideoJS player instead of the standard HTML5 player.

Sources:

Log4J Error: “log4j:WARN No appenders could be found for logger”

I recently got these errors when working on a Java web app:

[ERROR] log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
[ERROR] log4j:WARN Please initialize the log4j system properly.

My issue was that my project utilized Log4J2 and a dependency in my pom.xml utilized Log4J. To find which dependency is to blame, comb through the output of the mvn dependency:tree command.

There are a few solutions that could be utilized including changing the dependency to Log4J2, adding a log4j.properties file to the project outputting error messages, or adding a log4j.properties file to the dependency. Adding a log4j.properties file to the dependency made most sense in my case; I didn’t want every project that refers to the dependency to have to define and populate a log4j.properties file. We will go over adding a log4j.properties file to the dependency itself.

Navigate to the resources directory of the offending dependency and create an empty file named log4j.properties. Populating this file with any valid configuration should get rid of the appender error. Remember, this artifact must be published and then referred to the original project.

That’s it! Your error should be fixed!

tl;dr
Navigate to dependency that utilizes log4j and define and populate a log4j.properties file in the resources directory.

SLF4J Error: SLF4J: Class path contains multiple SLF4J bindings.

Recently, I received these errors when working on a Java web app:

[ERROR] SLF4J: Class path contains multiple SLF4J bindings.
[ERROR] SLF4J: Found binding in [jar:file:{userDirectory}/WEB-INF/lib/log4j-slf4j-impl-2.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[ERROR] SLF4J: Found binding in [jar:file:{userDirectory}/.m2/repository/org/apache/logging/log4j/log4j-slf4j-impl/2.2/log4j-slf4j-impl-2.2.jar!/org/slf4j/impl/StaticLoggerBinder.class]
[ERROR] SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
[ERROR] SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]

The offending dependency is the log4j-slf4j-impl dependency. Here’s what this dependency looks like in my pom.xml:

<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-slf4j-impl</artifactId>
	<version>{my_version_number}</version>
</dependency>

This error simply means that there are two jars that are binding to SLF4J. The solution is trivial. You must make it so that only one jar can bind with SLF4J.

To fix this, change the scope tag in your pom.xml to provided. This will require that the server that this app runs on provide this dependency. Here’s how we do this:

<dependency>
	<groupId>org.apache.logging.log4j</groupId>
	<artifactId>log4j-slf4j-impl</artifactId>
	<version>{my_version_number}</version>
	<!-- This scope tag prevents multiple bindings. It requires the server to provide the dependency at runtime. -->
	<scope>provided</scope>
</dependency>

Now, rerun your app and you shouldn’t see those errors anymore.

This isn’t necessarily the ideal solution because now we have a dependency that isn’t managed Maven. In some cases, changing the scope tag to provided is the only solution that works.

Another solution is to use the mvn dependency:tree command to comb through your dependencies to see if a dependency is pulling in a log4j-slf4j-impl jar. If so, utilize maven’s excludes tag to exclude the log4j-slf4j-impl from the associated dependency. I personally didn’t use this solution so I am not going to go into more detail but googling “maven exclude tags” should give you a place to start; I don’t want to give out information that I haven’t personally tested.

So, remember, the problem is you have two log4j-slf4j-impl jars on your classpath. You need to make it so that only one log4j-slf4j-impl jar is on your classpath.

Google GWT: Editing Server Side GWT Code with Partial Recompilation

This article is meant to teach developers how to edit GWT server side code with partial recompilation. That is to say, to teach developers how to avoid having to completely restart the GWT app. I’ve decided to author this article because I’ve recently worked with a team that did not know this ability existed or rather, could not find a way to setup partial recompilation.

Use Case: Reduce GWT application compile time and increase developer productivity.

Prerequisites: The gwt-maven-plugin org.codehaus.mojo is placed in your pom.xml.

  1. Run project with mvn gwt:debug in the command line. Wait until “[INFO] Listening for transport dt_socket at address: 8000”
  2. Listen on port 8000 with your preferred IDE utilzing a remote configuration. If this is confusing, you can follow the debugging tutorial located at Google GWT: Debugging Server Side GWT Code.
  3. Edit any code in the server package.
  4. Reload the changes in the IDE (Control + Shift + F9 in Intelilj).
  5. Optional: Navigate to “GWT Development Mode” window -> click “Jetty” tab -> click “Restart Server”. I’ve noticed that with larger code changes this is required but not for small code changes. The disadvantage is that it takes time to restart the server. If possible, try to avoid this.
  6. Set breakpoints to verifying that the code that you changed actually updated.

That’s it! You can partially recompile GWT apps!

Google GWT: Debugging Server Side GWT Code

I recently was working on a project utilizing Google GWT. Many of the developers did not know how to setup and use the debugger with Google GWT projects. Instead, they were relying on logging. Logging is a great tool but a good debugger is invaluable.

This article seeks to allow a developer to debug GWT server side Java code. For this tutorial, we will be utilizing Intellij IDEA but fear not, Eclipse can do the same thing.

We will first assume that the gwt-maven-plugin org.codehaus.mojo is placed in your pom.xml. If you have not set this up, feel free to learn more here.

After verifying this, navigate to the root directory of your project and run the application utilizing “mvn gwt:run”. Now, open up your application and play around with it just to make sure everything is working correctly. This is important to minimize any variables that could cause failure when trying to setup the debugger.

Following this, rerun the project in debug configuration utilizing “mvn gwt:debug”. This will allow a debugger to attach on to localhost with port 8000. Now, navigate to your preferred IDE and create a “Remote” debug configuration that listens on localhost with port 8000. Name this remote debug configuration “gwt debug”.

For Intellij, your settings should look like this:

intellij_remote_debug_configuration_for_gwt

In Intellij, go to “Run -> Debug” and click the remote configuration that you created called “gwt debug”. Now, set a breakpoint in your application, open the application in your browser, and then watch the IDE stop on your breakpoint! Remember, the breakpoint must be under the “server” package!

Let’s Encrypt Upgrade: Error during SSL Handshake with remote server

Recently, I had to upgrade a LetsEncrypt SSL certificate. I issued the commands:

sudo service apache2 stop
./certbot-auto renew # Assumes you are in the correct directory of 'certbot-auto'
sudo service apache2 start

I tested the site and everything seemed to be working correctly. Unfortunately, a little while later, I got this error message:

Proxy Error

The proxy server could not handle the request GET /.
Reason: Error during SSL Handshake with remote server

Apache/2.4.7 (Ubuntu) Server at {my_web_site} Port 443

I retraced my steps and I forgot to recreate {my_web_site}’s keystore file. This site was a Spring Boot application and was utilizing a .p12 file. Here are the steps to regenerate this file:

cd /etc/letsencrypt/live/{my_domain_name}/ # Changes directory to Let's Encrypt directory.
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name tomcat -CAfile chain.pem -caname root # Generates keystore.p12 file
# At this point, you will be prompted to give a password. It makes sense to give the same password as the one located in your config files so you don't have to update the 
# config file. If you choose to use a new password, you will have to update your app's config file to the new password. 

At this point, the new keystore file has been generated and the next step is to simply replace the old keystore file and republish the application.

If Spring Boot is being utilized, and you are not comfortable overwriting the old keystore file, simply go to your configuration file and find the "server.ssl.key-store={value}" key-value pair and replace the value with the new keystore location. You may need to update the "server.ssl.key-store-password={value}" key-value pair if you changed the keystore’s password when the openssl command prompted a password. It is easiest to avoid these updates sticking to the same keystore location and password.