Java net malformedurlexception
Java Exception Handling – MalformedURLException
Moving along through the in-depth Java Exception Handling series we’ve been going through, we next arrive at the MalformedURLException. A MalformedURLException is thrown when the built-in URL class encounters an invalid URL; specifically, when the protocol that is provided is missing or invalid.
In today’s article we’ll examine the MalformedURLException in more detail by looking at where it resides in the overall Java Exception Hierarchy. We’ll also take a look at some fully functional code samples that illustrate how a basic HTTP connection might be established using the URL class, and how passing improper URL values to it can result in MalformedURLExceptions , so let’s get started!
The Technical Rundown
All Java errors implement the java.lang.Throwable interface, or are extended from another inherited class therein. The full exception hierarchy of this error is:
Full Code Sample
Below is the full code sample we’ll be using in this article. It can be copied and pasted if you’d like to play with the code yourself and see how everything works.
This code sample also uses the Logging utility class, the source of which can be found here on GitHub.
When Should You Use It?
As the official documentation states, a MalformedURLException is thrown either when “no legal protocol could be found in a specification string,” or when “the string could not be parsed.” In practice, modern Java versions have particularly robust string parsing capabilities, so the vast majority of MalformedURLException occurrences will be due to the former problem: an invalid or unrecognized protocol . The parlance used in Java (and elsewhere) for terms like protocol can be a little confusing, so we’ll briefly refresh ourselves on what this means in the realm of URLs.
To begin with, the broader term for identifiers of network resources is “Unified Resource Identifier”, or URI as it’s more commonly known. A URI is merely a string of characters that identify a resource over a network. Uniformed Resource Locators, or URLs , are a type of URI . A URL is unique in that it typically includes multiple forms of information about accessing the resource, including the protocol , the domain , and the resource to be requested. For example, in the URL https://airbrake.io/blog/ the specified protocol is https , the domain is airbrake.io , and the resource is /blog/ .
It’s worth noting that the protocol section is often referred to as the scheme in the parent URI object type, because a URI can contain many different types of schemes to indicate how the resource should be accessed. For example, a scheme of https is common for URLs , but a scheme value of file might be used to access a local file resource. Moreover, many custom URI schemes exist, which allow applications to perform special actions and open resources on behalf of other applications. For example, the popular Steam online gaming platform will recognize and open URIs with a scheme of steam , as shown in the developer documentation.
All that said, since the MalformedURLException in Java is typically thrown via the URL class, it stands to reason that the URL class refers to the scheme portion of the URL as the protocol . To illustrate this in action we begin with a simple HttpMethod enumeration:
This will come in handy in a moment, when we need an easy way to specify the HTTP method we’ll be using for our connection. Speaking of which, we’ve also created a custom HttpResponse class to help simplify the creation and connection process, in order to ultimately retrieve a response from a particular URL that we wish to connect to:
I’ve opted to use a Factory Design Pattern , which we explored in our Creational Design Patterns: Factory Method article, which allows us to execute a sub-method after instantiating a new HttpResponse object. Specifically, we want to execute the initialize() method after the constructor completes, but we also need a way to avoid race conditions, which is where we might get unexpected results if our code is performing multiple connections simultaneously, and where our code could behave differently depending on the order of execution. By avoiding race conditions via the factory method pattern, we ensure that execution always occurs in the order we require.
Thus, client code wishing to create a new HttpResponse instance can only access the create() method overloads, which creates a new HttpResponse instance via the private constructor, then invokes the initialize() method, before finally returning the generated HttpResponse object. The initialize() method is where we perform the actual connection attempt and retrieve the response, so we start by creating a new URL instance from the url property, then open an HTTPS connection to that url . We then set the request method using the string-converted httpMethod property, which is where the HttpMethod enum comes into play. Next, we retrieve the response code and, if it’s valid ( 200 ) we process the response by appending each line to an output and assigning the response to the response property.
As a result, client code that invokes the create() method can then immediately call the getResponse() method, which retrieves the formatted (or null ) response property value of the HttpResponse instance:
To test this out we’ll create a handful of HttpResponse instances, passing slightly different URL string arguments each time:
The first test produces the following output:
Here we can see that everything appears to be working. We start by establishing a connection to https://airbrake.io , set the request method to GET , set the User-Agent to tha latest Chrome agent string, and get a response code of 200 . The full response contains 484 lines, so we truncate that result down to the maximum of 200 characters, as specified in the HttpResponse.MAX_RESPONSE_LENGTH property.
Next, let’s try another test to connect to the slightly incorrect htps://airbrake.io URL :
Immediately we get a MalformedURLException , indicating that the protocol value at the start of our URL is invalid. As previously discussed, URLs are a sub-classification of URIs , so while a URI can have a wide range of standard and custom scheme values, a URL can only have a select handful of accepted protocol values, and htps is not one of them.
Our third test attempts to connect to https://airbrakeio :
Here we see everything works and no MalformedURLException is thrown, but we actually get an UnknownHostException instead. This is because, while https://airbrakeio is a perfectly valid form of URL , it isn’t a recognized host . The same is true when we try to use an invalid character in our host name ( , ):
The Airbrake-Java library provides real-time error monitoring and automatic exception reporting for all your Java-based projects. Tight integration with Airbrake’s state of the art web dashboard ensures that Airbrake-Java gives you round-the-clock status updates on your application’s health and error rates. Airbrake-Java easily integrates with all the latest Java frameworks and platforms like Spring , Maven , log4j , Struts , Kotlin , Grails , Groovy , and many more. Plus, Airbrake-Java allows you to easily customize exception parameters and gives you full, configurable filter capabilities so you only gather the errors that matter most.
Check out all the amazing features Airbrake-Java has to offer and see for yourself why so many of the world’s best engineering teams are using Airbrake to revolutionize their exception handling practices!
java.net.MalformedURLException: no protocol #8
Comments
Copy link Quote reply
whgibbo commented Apr 7, 2018
Hi,
Was wondering if anybody had come across this issue:
Exception in thread «main» java.util.concurrent.ExecutionException: java.net.MalformedURLException: no protocol:
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at PublicClient.getAccessTokenFromUserCredentials(PublicClient.java:55)
at PublicClient.main(PublicClient.java:27)
Caused by: java.net.MalformedURLException: no protocol:
at java.base/java.net.URL.(URL.java:627)
at java.base/java.net.URL.(URL.java:523)
at java.base/java.net.URL.(URL.java:470)
at com.microsoft.aad.adal4j.HttpHelper.openConnection(HttpHelper.java:119)
at com.microsoft.aad.adal4j.HttpHelper.executeHttpGet(HttpHelper.java:48)
at com.microsoft.aad.adal4j.HttpHelper.executeHttpGet(HttpHelper.java:42)
at com.microsoft.aad.adal4j.WSTrustRequest.execute(WSTrustRequest.java:82)
at com.microsoft.aad.adal4j.AuthenticationContext.processPasswordGrant(AuthenticationContext.java:990)
at com.microsoft.aad.adal4j.AuthenticationContext.access$000(AuthenticationContext.java:69)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:178)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:168)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.base/java.lang.Thread.run(Thread.java:844)
I’ve change the the CLIENT_ID to match the ApplicationId for the service that I registered, provided my username and password when prompted and got the error above.
Do I need to create a special/service account to use the sample ?
This comment has been minimized.
Copy link Quote reply
whgibbo commented Apr 9, 2018 •
Ok so made a little headway..
So I was using the credit on my MDSN account, which meant it was hooking into our corporate directory. As there doesn’t seem to be way to create your own 🙁
So I signed up a trial account and setup an Azure AD there.. So no longer get a corporate a malformed url.. But getting:
So will now look into how to solve these 2 issues.. Any help or suggestion would be appreciated 🙂
This comment has been minimized.
Copy link Quote reply
sangonzal commented Apr 19, 2018
Hi @whgibbo did you click on «Grant Permissions» in the «Required Permissions» blade in the registered application settings?
This comment has been minimized.
Copy link Quote reply
whgibbo commented Apr 26, 2018
Yes I think that was the missing step 🙂 Thanks..
So now I have it working for the a personal azure account, but wanted to try on MSDN account, which is hooked to the corporate directory.
But this yields the following:
Exception in thread «main» java.util.concurrent.ExecutionException: java.net.MalformedURLException: no protocol:
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at PublicClient.getAccessTokenFromUserCredentials(PublicClient.java:74)
at PublicClient.main(PublicClient.java:39)
Caused by: java.net.MalformedURLException: no protocol:
at java.net.URL.(URL.java:593)
at java.net.URL.(URL.java:490)
at java.net.URL.(URL.java:439)
at com.microsoft.aad.adal4j.HttpHelper.openConnection(HttpHelper.java:119)
at com.microsoft.aad.adal4j.HttpHelper.executeHttpGet(HttpHelper.java:48)
at com.microsoft.aad.adal4j.HttpHelper.executeHttpGet(HttpHelper.java:42)
at com.microsoft.aad.adal4j.WSTrustRequest.execute(WSTrustRequest.java:82)
at com.microsoft.aad.adal4j.AuthenticationContext.processPasswordGrant(AuthenticationContext.java:990)
at com.microsoft.aad.adal4j.AuthenticationContext.access$000(AuthenticationContext.java:69)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:178)
at com.microsoft.aad.adal4j.AuthenticationContext$1.call(AuthenticationContext.java:168)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
So when I step thru the code, I can see with the MSDN account that the userDiscoveryResponse is a Federated account (AuthenticationContext.java — Line 989). It then appears to obtain the getFederationMetaDataUrl, which is returning an empty string. Which is causing the MalformedURLException..
So will keep searching.
This comment has been minimized.
Copy link Quote reply
gabriel-rcpereira commented Dec 10, 2019
Hi @whgibbo
The federated account isn’t able to perform the authentication through Azure AD. The federated account store the User Credential into the OnPremisse directory.
I hope help you.
This comment has been minimized.
Copy link Quote reply
TiagoBrenck commented Feb 7, 2020
This sample has been archived.
- © 2020 GitHub, Inc.
- Terms
- Privacy
- Security
- Status
- Help
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Особенности HttpUrlConnection из java.net
сегодня постараюсь рассказать о том, как можно отправить запрос и прочитать ответ от HTTP сервера, используя URLConnection из библиотеки JRE.
Сейчас изучаем Java в онлайн режиме. Вся наша команда использует Slack для работы и общения. Для получения информации о пользователях, используем Slack API. Чтобы долго не рассказывать про сам API (это тема для отдельной статьи), скажу коротко: Slack API построен на HTTP протоколе, для получения информации о пользователях, нужно отправить запрос с URI в котором должно быть имя метода из API на host-адресс api.slack.com Вот список некторых методов:
- users.list
- chat.postMessage
- conversations.create
- files.upload
- im.open
Для получения списка юзеро нужен метод users.list. Формируем URI — /api/users.list в теле запроса должен быть токен аутентификации в форме application/x-www-form-urlencoded, то есть запрос должен выглядеть примерно так (но есть один нюанс который будет ниже):
Я знал про библиотеку Apache HttpComponents, но для иследовательских целей будем использовать средства доступные в стандартной библиотеке Java 8, а именно имплементацию java.net.URLConnection.
Для получений сущности URLConnection нужно использовать объект класса java.net.URL, его конструктор принимает тип String где помимо всего должен быть указан протокол – в нашем случае https.
После получения сущности URL, вызываем метод openConnection() который возвратит нам сущность HttpsUrlConnection.
При этом нужно обработать или пробросить MalformedUrlException и IOException.
После этого переменная connection будет хранить ссылку на объект HttpsUrlConnectionImpl. По умолчанию будет формироваться GET-запрос, для того чтобы добавить Header используем метод setRequestProperty(), который принимает key и value. Нам здесь нужно установить Content-Type который имеет значение application/x-www-form-urlencoded. Ну, и мы это делаем!
Теперь осталось только отправить запрос записав в тело наш токен и лимит. Для этого нужно установить поле doOutput объекта connection в положение true, используя метод setDoOutput();
Далее самая интересная часть — нужно как-то передать наше тело запроса в OutputStream. Будем использовать OutputStreamWriter:
Есть один нюанс: после того, как мы вызвали метод getOutputStream() метод запроса меняется на POST, так как GET не предусматривает наличие request body, но благо что slack ни ставит твёрдое ограничение на метод поэтому всё было хорошо. И поэтому GET-запрос должен выглядеть так:
Но я не стал уже переделывать. И вместо этого наш запрос получился таким:
(*некоторые headers ставятся самим HttpsUrlConnection и здесь они отсутствуют)
И так чтоб записать наше тело запроса пользуемся write();.
После этого наш запрос будет отправлен, и мы можем прочитать полученный ответ. Важно закрывать OutputStream или делать flush(), перед тем как получать InputStream, иначе данные не уйдут из буффера(как альтернатива можно использовать PrintStream — в методе println() по умолчанию вызывается flush()). Для чтение использовал BufferedReader:
(*используем lines() чтобы получить Stream на выходе; rn – символ CRLF – вставляет переход на новую строку)
И, если мы успешно проходим аутентификацию, переменная respBody должна хранить наш ответ от сервера, что в нашем случае является JSON объектом. После этого, его можно отправлять на следующий этап обработки.
После некоторой оптимизации всё выглядет так: