Glen Mazza's Weblog

https://glenmazza.net/blog/date/20210404 Sunday April 04, 2021

Accessing Salesforce using Spring Security 5's OAuth2 client

For the two Salesforce OAuth2 flows discussed in my earlier blog post, namely the JWT bearer token and username/password flows, I've created a sample Spring Boot app on Github. This app will obtain access tokens using the flow you configure and make a sample call to Salesforce's standard "Account" resource. Note both these server-to-server flows assume a hardcoded single resource owner for all API calls. (For clients handling multiple users logging in and authorizing calls, Salesforce's Web Server Flow is more appropriate, there are some links at the bottom for information on this flow.)

To run the sample, first create an application.properties file in the resources folder with the configuration necessary for the flow you are using (there is a template file in that folder specifying what is needed for each flow type, with the earlier blog post providing instructions on how to obtain these values). The sample's SalesforceOAuth2Config class reads that configuration, and will halt on startup with informational messages if anything needed is missing. The app can be run from an IDE like IntelliJ or command-line via gradle bootRun, and it will make a sample call retrieving one Salesforce Account object every 30 seconds until halted.

To create the app, I used Spring's Initialzr with the latest Spring Boot release version and Java 11, and added the Spring Web, Spring Reactive Web, and OAuth2 Client dependencies. During development I also brought in a few extra libraries listed in the build.gradle. The Username/Password flow is supported out of the box by Spring, but the JWT bearer token flow requires some extra classes that I implemented following Spring's source code for their standard password and client grant flows. The files are commented to aid in understanding this flow:

What happens when access tokens expire? The WebClient call in SalesforceService has a retry(1) setting that allows one additional call to the resource server in case of an error such as using an expired access token. In such cases, for the first call, the failure handler in SalesforceOAuth2Config removes the authorized client instance (which has the invalid access token) from memory. For the retry call, SalesforceJwtBearerOAuth2AuthorizedClientProvider notes that there is not an authorized client instance anymore so proceeds to obtain a new access token to allow the second call to proceed. This functionality can be verified by revoking the access token from either Salesforce Setup's Session Management screen or from Connected Apps usage, and making a subsequent resource API call, it should seamlessly provide the data. Code breakpoints can also be used to confirm another access token was requested.

Additional Resources

Posted by Glen Mazza in Programming at 07:00AM Apr 04, 2021 | Tags:  oauth2  salesforce  spring | Comments[0]

https://glenmazza.net/blog/date/20210328 Sunday March 28, 2021

Making Salesforce API calls with Postman

Salesforce's Mohith Shrivastava's second Connected App tutorial shows how the JWT Bearer Token Flow can be used with Postman to obtain access tokens. Separately, SFDCStop shows how to use an access token to retrieve data from Salesforce. Summary of the process for getting an access token via JWT Bearer Token flow is given below, along with the alternative Username-Password flow.

Obtaining Access Token via JWT Bearer Token Flow

Mohith's second tutorial largely follows the Trailblazer documentation for creating the JWT necessary for obtaining an access token. First, within Postman, open a POST request to https://test.salesforce.com/services/oauth2/token (or login.salesforce.com for production) with two query attributes, grant_type hardcoded to urn:ietf:params:oauth:grant-type:jwt-bearer and assertion with a value that can be generated at JWT.io as follows:

  1. Place {"alg":"RS256"} in the JWT header.

  2. Place the following in the JWT payload, updating the iss value with the Client ID of the connected app, the aud value with the login or test URL being accessed, the sub with the Salesforce resource owner (the user ID, usually expressed as an email), and exp value being the ten-digit current UNIX timestamp. Ensure there are no spaces or carriage returns in the payload:

    {"iss":"--client id--","sub":"--salesforce user--","aud":"https://test.salesforce.com","exp":"1616865336"}

    You may also wish to add a "jti" field (JWT ID), the value of which can be a randomly generated UUID. As stated in the Trailblazer documentation linked above, if a "jti" field is added, Salesforce will make sure the JWT hasn't been used to make a prior access token request, serving as a guard against replay attacks. If it has been used, it will return a 400 response code with message { "error": "invalid_request", "error_description": "jti already in use"}.

  3. Finally, in the Verify Signature portion, as generated in the previous tutorial, place the PublicCert.crt contents and the private key found in key.pem (including the BEGIN/END delimiters) in the corresponding boxes. JWT.io should report "Signature Verified", upon which you can copy the left-side as the assertion value into the Postman call. Make the call and you should get an access token in response.

    BearerTokenRequest

Obtaining Access Token via Username-Password Flow

This process is much more straightforward as no keys are used. As shown in the Salesforce documentation, you can simply make a POST request with the following five query parameters: grant_type, client_id, client_secret, username, and password.

PostmanViaUsernamePwd

Making Salesforce calls using the Access Token

As demo'ed in the SFDCStop video, can create a GET request to say https://yoursalesforceinstance.salesforce.com/services/data/v50.0/query?q=SELECT+Name,Type+FROM+Account. Under the Authorization tab, select "Bearer", copy-and-paste the access token in, and make the API call.

SOQLQuery

More information on SOQL calls are available here.

Posted by Glen Mazza in Programming at 07:00AM Mar 28, 2021 | Tags:  oauth2  salesforce  postman | Comments[0]

https://glenmazza.net/blog/date/20210321 Sunday March 21, 2021

Creating a Salesforce Connected App

Salesforce Connected Apps provide the conduit for data transfers between Salesforce and third-party apps. Salesforce's Mohith Shrivastava offers four-part series on Connected Apps, roughly four hours of instruction in total, helpful for visual walk-through of configuration. Below are simple steps I've followed for configuring a Connected App, but as always the official documentation should be at least reviewed to make sure all security matters are properly taken care of.

Creating credentials to access a Connected App.

The OAuth Authorization Flows section in the Salesforce Trailblazer documentation details the various methods (or "flows") available for working with Salesforce data externally. Below lists configuration for two of the flows usually best for server-to-server integration, i.e., without an active user logging in and activating the processes. For this use case, Salesforce recommends creating an integration user. Instructions here and here seem to best for creating an integration user. However, the profile options for choosing "API Enabled" and "API Only User" (i.e., user can not directly log into Salesforce) appear not to be under a "Administrative permissions" section anymore but under the System: System Permissions option when one creates the integration user's profile.

  • OAuth 2.0 JWT Bearer Flow: Accessing the application using a public/private key pair. Here, the public cert is uploaded to the Salesforce connected app, while the requests are signed by the client using the private key. The Connected App relies on the successful decrypting of the message to confirm the request is coming from the client. In this case, the user's login and connected app consumer key are needed by the client, but not the user's password or the connected app client secret.

    A locally-made key pair is sufficient for this access technique, I've used a combination of the Java keytool and OpenSSL for this. Steps:

    1. Create a Java PKCS12 keystore using the following command. Keystore passwords here don't matter as they will soon be discarded (keys will be worked with directly). Note that validity given below is in days, whatever value you choose, note the key will need to be replaced with it expires:

      keytool -genkeypair -keyalg RSA -sigalg SHA1withRSA -validity 1095 -storepass mypassword -storetype PKCS12 -keystore tempKeystore.p12 -alias myappkey
    2. Create a public certificate to be uploaded to the Salesforce Connected App:

      keytool -export -rfc -keystore tempKeystore.p12 -storepass mypassword -file PublicCert.crt -alias myappkey
    3. As for the public key itself, it is not needed for making Salesforce calls, but can be obtained if desired via:

      openssl x509 -pubkey -in PublicCert.crt -text -noout
    4. Finally, extracting the private key from the keystore. Two formats are provided below, pem and (encoded) DER. The latter is usually used for Java, and obtained from the former via the commands below. The private key needs to be kept secure as anyone with it can access the Salesforce Connected App, once the latter is configured with its public key.

      openssl pkcs12 -in tempKeystore.p12 -passin pass:mypassword -nodes -nocerts -out key.pem
      openssl pkcs8 -topk8 -inform PEM -outform DER -out key.der -nocrypt -in key.pem
      openssl base64 -in key.der -out keyDerEncoded.txt
      
  • OAuth 2.0 Username-Password Flow for Special Scenarios: Obtaining access tokens using the resource owner's username and password instead of X.509 key pair. Salesforce does not ordinarily recommend this flow, quote: "Use it only if there’s a high degree of trust between the resource owner and the client, the client is a first-party app, Salesforce is hosting the data, and other grant types aren’t available. In these cases, set user permissions to minimize access and protect stored credentials from unauthorized access."

    If you're heavily using Postman to obtain access tokens, this method is much easier and faster than manually creating JWT bearer tokens, of course be careful though that the user and client credentials don't get exposed to others who shouldn't have them.

Salesforce Connected App Configuration
  1. Log into Salesforce and click the gear on the upper right side to choose Setup (illustration below). Once the setup window appears, on the left-side search box search and select "App Manager". Once App Manager is up, select the New Connected App button on the right-side.

    SCA_SetupButton

    SCA_NewConnApp

  2. Click on the "Enable OAuth Settings" checkbox to place in configuration similar to the below. See the official documentation for an explanation of options available, also note the refresh_token role granted below would be unneeded for either of the two flows above (neither use refresh tokens). If using the Bearer Flow, be sure to click on "Use Digital Signatures", place the public key generated earlier into a file and upload. The callback URL will be ignored for either of the two flows, but a value needs to be provided regardless. When done, hit “Save” at the top, and then the “Manage” button, and then “Edit Policies” (covered in next step).

    SCA_OAuthSettings
  3. On the Policies page, here is where you may wish to add IP Address restrictions to limit from where approved clients may call the application. Click Save and scroll to the Profiles section (next step).

    SCA_OAuthPolicies

  4. For profiles, add the profile of the User being used to make the Salesforce calls. If an Integration User profile was created as suggested above, for example, choose that. Make sure the user associated with the calls is part of that profile.

  5. Back in App Manager, in the table of apps, go to the last column of the new connected app and choose View. As mentioned earlier, just the consumer key will be needed for the Bearer flow, but both that and the consumer secret for the Username-Password flow. As with the private key in the Bearer flow, make sure the client secret is stored confidentially, should it get exposed the connected app should be deleted and a new one which will have a different consumer key and secret created.

Posted by Glen Mazza in Programming at 07:00AM Mar 21, 2021 | Tags:  salesforce  oauth2 | Comments[0]

https://glenmazza.net/blog/date/20200622 Monday June 22, 2020

Revisiting Revenue Tariffs

Summary: This article encourages usage of the revenue tariff as the first source for funding the U.S. federal government, calibrated at a rate to maximize the cash flow into the federal treasury. These funds should be used to exempt corporate taxation and other fees on U.S.-based manufacturing, allowing them to produce items at a lower, more competitively priced cost. More domestic employment and reduced cash transfers overseas will result in cost savings for the government that grow over time. Apply those savings in turn towards having ever-higher minimum income thresholds before the personal income tax comes into effect.

Revenue tariffs--a method of funding the government's responsibilities by means of a tax we place on ourselves when we buy a new foreign-made product--play just a minor role in the federal budget today. In 2018 they provided only about $41 billion or 1.25% out of a $3.3 trillion budget, with personal and corporate taxes providing about 57% (the payroll tax for Social Security and Medicare making up the bulk of the remainder). However, with the exception of an income tax for a twelve year period during the Civil War and Reconstruction, providing about 20% of the nation's income, we did not have an income tax until the passing of the 16th Amendment in 1913 which allowed the federal government to collect tax not proportional to a state's population. The 1960 Treasury Report (four pages in question, compare customs vs. total receipts) show revenue tariffs supplying 80-90% of government needs up to the Civil War, and about 60% through the second half of the 19th century and first decade of the 20th. Income taxes first overtook revenue tariffs in 1917 ($360 million to $226 million), and in the following year blew past them for funding World War I ($2.3 billion vs. $180 million). In the 1920's tariffs bounced back a bit, providing about 10-20% of government revenue, before decreasing in importance again. Since the end of World War II tariffs have been providing the 1-2% that they deliver to this day.

In discussing tariffs, it is necessary to distinguish revenue tariffs--the subject of this article--from protective (or prohibitive) tariffs, as they differ in their manner in which they boost domestic manufacturing and are at opposite ends of whether the purchase of foreign-made products should play a role in funding of government. Most journalists supporting tariff-free access for foreign-made products to the United States (i.e., free trade) use "tariffs" in the easier-to-rebut protective sense, causing revenue tariffs to miss proper consideration.

  • The revenue tariff is a tax placed on new foreign-made products that is intended to fill government coffers allowing taxes to be reduced elsewhere in a targeted manner. For the case of a $120 Chinese-made computer monitor that presently could not be made for less than $400 in the United States, for example, a 20% revenue tariff places $24 in the federal treasury, making the item $144 for consumers. It still does not cause one to buy the $400 U.S.-made monitor, however the tariff money raised allows for removing taxation on U.S. manufacturers of all products, dropping their prices and hence expanding the fields of other U.S. products which can now be competitively priced. For the case of a foreign-made item selling for $10 and a U.S.-made one that can be produced for $13, a 20% tariff raises the price of the former to $12 and removed corporate taxes and other revenue-generating fees from the latter may drop its price to $11, enabling that product to be domestically made.

  • Protective tariffs are not intended to provide revenue for the U.S. treasury but are instead meant to compel purchase of the American-made product. For the case of the $120 Chinese vs $400 US computer monitor, we place a 300% tariff on the former, making it $480, so the American monitor gets bought instead and no tariff revenue sent to the federal treasury. Without this additional source of government revenue, America's tax reliance on personal and corporate income taxes remains largely the same, although probably reduced somewhat due to higher employment creating more taxpayers. Protective tariffs form a direct way of forcing people to buy domestic even where it's not cost-effective, dropping standard of living in the process. Although American manufacturers would still need to compete against themselves, providing such competition exists, there would be reduced incentive to compete well against foreign manufacturers as they can always rely on a protective tariff to make the foreign product more expensive.

It is perhaps instructive to note that free traders and supporters of protective tariffs find themselves in agreement on the inappropriateness of government using the sale of foreign-made products to fund its responsibilities, but for different reasons, the former because that would mean the tariff rate is nonzero, the latter because that would mean the tariff rate wasn't sufficiently high enough to compel the purchase of the American product. Free traders and supporters of revenue tariffs on the other hand differ on whose manufacturing--domestic or foreign--they want to see taxed. With the former, corporate taxes on domestic manufacturing and income taxes are to be used however much is necessary to avoid needing to obtain revenue from foreign products, keeping the latter at the lowest possible price. Their position seems analogous to arguing that foreign-made products should be exempt from state sales taxes, as that would form an unacceptable "barrier to trade", with the sales tax doubled on American-made products to make up for the lost revenue, and when American products get sold less as a consequence, to raise the sales tax on those dwindling American-made products even higher to make up for that lost revenue, a snowballing effect pushing most all production overseas.

Supporters of revenue tariffs are not hostile to foreign-made products, as per this system imports are needed to pay the taxes. Due to wide divergences in labor costs and employee regulations many products will continue to be made overseas. It is not acceptable, however, for foreign-made products to gain an edge because the U.S. government, in exempting taxation on foreign-made products, had to place taxes on domestic-made ones to make up the lost revenue, unnecessarily inflating the latter's price and causing domestic unemployment. Free trade, the increasing of the price of domestic products via taxation in order to drop the price of foreign-made products by keeping them tariff-free, is really reverse protectionism of foreign products over American-made ones.

What makes revenue tariffs such an efficient form of taxation, and why government should therefore always look at them as the first source of funding, is that they not only provide income for the government but play an unparalleled role in reducing the need for government outgo, the latter of which income taxes simply don't provide. When we're not buying $450 billion a year from China, our military doesn't need to spend as much to defend against her (or North Korea for that matter), saving money and creating more peace of mind. With greater meaningful employment in domestic manufacturing, social costs (welfare, crime/prisons, drug addictions, etc.) are also reduced. While mitigating the economic ills of free trade provides lots of jobs for government workers--perhaps making many of them and their private-sector contractors among the bigger supporters of free trade--these public sector positions require high taxation and mounting debt to support. Further, with manufacturing providing more decent non-college-degree requiring job opportunities, there would be a reduction in people seeking university degrees in an attempt to avoid the main alternative of lower-level service-sector jobs, degrees that often provide little more but a return to the same service-sector jobs but with the additional burden of four lost years and sizeable college loan debt.

Support for the revenue tariff is based on the belief that paying one dollar in revenue tariffs will save several dollars in income taxes over time and the belief that the society brought about by revenue tariffs is much better than one based primarily on income taxes. With the latter, one is usually just fixing the problems of an underperforming society due to lack of meaningful employment and heavy cash transfers to our Chinese adversary. With the revenue tariff, we're instead directing our taxes towards fellow Americans having meaningful work in the private sector and taking advantage, at income tax time, of the societal benefits that result.

An eloquent defense of tariffs can be found in Abraham Lincoln's Circular from the Whig Committee of 1843, in which he compares tariffs vs. direct (property) taxes: The tariff is the cheaper system, because the duties, being collected in large parcels at a few commercial points, will require comparatively few officers in their collection; while by the direct-tax system the land must be literally covered with assessors and collectors, going forth like swarms of Egyptian locusts, devouring every blade of grass and other green thing. And, again, by the tariff system the whole revenue is paid by the consumers of foreign goods, and those chiefly the luxuries, and not the necessaries, of life. By this system the man who contents himself to live upon the products of his own country pays nothing at all. And surely that country is extensive enough, and its products abundant and varied enough, to answer all the real wants of its people. In short, by this system the burden of revenue falls almost entirely on the wealthy and luxurious few, while the substantial and laboring many who live at home, and upon home products, go entirely free. By the direct-tax system none can escape. However strictly the citizen may exclude from his premises all foreign luxuries,—fine cloths, fine silks, rich wines, golden chains, and diamond rings,—still, for the possession of his house, his barn, and his homespun, he is to be perpetually haunted and harassed by the tax-gatherer.

Another special characteristic of revenue tariffs is that it is no longer necessary to be concerned about buying made-in-America products. Either you're buying American (great!), or you're flushing money into the U.S. treasury, providing the financing to keep domestic manufacturing cheaper, with other U.S. products being more easily sold to others as a consequence. It's win-win. This is a considerable improvement over the status quo which punishes caring for your fellow Americans, where those doing the right thing by buying American end up paying more in taxes (both directly via sales tax on higher priced U.S. products and indirectly built into the product by the taxes the American manufacturers and their workers pay) than those buying tariff-free foreign goods.

An tariff rate for initial consideration might be 20% world-wide with the exception of China which would have a 30% tariff. Why more for China? Similar to the gasoline tax meant to pay for roads -- the more gasoline one buys, the more one is driving, and hence the more of the road upkeep one should pay -- when we buy Chinese products we're strengthening their military and indirectly, North Korea's, causing us to need to spend more on defense to counteract them. Therefore we should be helping to cover those extra costs at the point of sale, so the more Chinese products each individual buys the more of the tax that individual properly pays.

One of the concerns about relying on revenue tariffs is that "other countries would retaliate!" and that American businesses would be worse off as a consequence. That would be a stronger argument with protective tariffs, but with revenue tariffs the level of blockage is less (again, we need imports to pay the taxes.) It's also based on an incorrect perception, that they haven't already been putting revenue or protective tariffs on our products all along. Much if not most free trade the U.S. has engaged in the past is of the one-way variety of them to us, seemingly the only direction that most free-trade supporting editorialists care about. As Patrick Buchanan noted, most countries use a VAT system which they exempt on products leaving their shores and place on foreign products coming in, serving effectively as a tariff that a VAT-less USA isn't counteracting.

Ultimately, we can't sell a product in foreign nations unless we're first manufacturing and selling the product here, and exempting U.S. domestic manufacturers from taxation provides the broadest nationwide benefit in allowing us to find and produce more things that, after being sellable in the USA, can next be sold world-wide. Also, as for retaliation, the $100 billion or so China buys from us, usually in agriculture, is primarily paid from the $450 billion that we buy from them, so those sales are easily made up as we spend more of our money on ourselves. Being their military competitor on Japan, Korea, and Taiwan, China has clear strategic reasons to buy as little from us as possible, making that country a poor investment for us. As for the oft-stated concern that tariffs on manufactured products would hurt the economic situation of our farmers (e.g., tariffs on Chinese products resulting in China buying less U.S.-grown soybeans), President Calvin Coolidge noted in his 1927 State of the Union address:

It is often stated that a reduction of tariff rates on industry would benefit agriculture. It would be interesting to know to what commodities it is thought this could be applied. Everything the farmer uses in farming is already on the free [i.e., untariffed] list. Nearly everything he sells is protected. It would seem to be obvious that it is better for the country to have the farmer raise food to supply the domestic manufacturer than the foreign manufacturer. In one case our country would have only the farmer; in the other it would have the farmer and the manufacturer. Assuming that Europe would have more money if it sold us larger amounts of merchandise, it is not certain it would consume more food, or, if it did, that its purchases would be made in this country. Undoubtedly it would resort to the cheapest market, which is by no means ours. The largest and best and most profitable market for the farmer in the world is our own domestic market. Any great increase in manufactured imports means the closing of our own plants. Nothing would be worse for agriculture.

Finally, even if it may be considered retaliation, it should be noted that the revenue tariff system is a legitimate tool for all nations to expand their wealth, particularly those not relying on a VAT, ensuring the products that can be made domestically are done so instead of relying on environmentally wasteful cross-oceanic shipping. In so doing, revenue tariffs provide another effective way of encouraging "Buy Local."

Posted by Glen Mazza in Other at 06:00AM Jun 22, 2020 | Comments[0]

https://glenmazza.net/blog/date/20191228 Saturday December 28, 2019

TightBlog 3.7 released, offers improved comment handling

TightBlog 3.7 released just now: (Release Page). This version requires a few database table changes over 3.6, if upgrading be sure to review the database instructions given on the release page. Features updated comment and spam handling processes, as described on the TightBlog Wiki.

Posted by Glen Mazza in Programming at 12:00AM Dec 28, 2019 | Comments[0]

https://glenmazza.net/blog/date/20191211 Wednesday December 11, 2019

TightBlog 3.6 Released!

Just-released TightBlog 3.6 (release page/screenshots/installation instructions) now provides an endpoint for embedding GitHub source code in your blog entries, see here for a sample and the Tightblog Wiki for more details. Previously I had to rely on third party tools hosted on other servers to accomplish the same, but happy to report this functionality is now available out-of-the-box with TightBlog.

Posted by Glen Mazza in Programming at 07:00AM Dec 11, 2019 | Comments[0]

https://glenmazza.net/blog/date/20191106 Wednesday November 06, 2019

Improving validation feedback in TightBlog

Tom Homberg provided a nice guide for implementing user-feedback validation within Spring applications, quite helpful for me in improving what I had in TightBlog. He creates a field - message Violation object (e.g., {"Name" "Name is required"}), a list of which is wrapped by a ValidationErrorResponse, the latter of which gets serialized to JSON and sent to the client to display validation errors. For my own implementation, I left the field value blank to display errors not specific to a particular field, and used it for both sending 400-type for user-input problems and generic 500-type messages for system errors.

Implementing this validation for TightBlog's blogger UI, I soon found it helpful to have convenience methods for quick creation of the Violations, ValidationErrorResponses and Spring ResponseEntities for providing feedback to the client:

public static ResponseEntity<ValidationErrorResponse> badRequest(String errorMessage) {
    return badRequest(new Violation(errorMessage));
}

public static ResponseEntity<ValidationErrorResponse> badRequest(Violation error) {
    return badRequest(Collections.singletonList(error));
}

public static ResponseEntity<ValidationErrorResponse> badRequest(List errors) {
    return ResponseEntity.badRequest().body(new ValidationErrorResponse(errors));
}

i18n can be handled via the Locale method argument, one of the parameters automatically provided by Spring:

@Autowired
private MessageSource messages;

@PostMapping(...)
public ResponseEntity doFoo(Locale locale) {
    ...

    if (error) {
        return ValidationErrorResponse.badRequest(messages.getMessage("mediaFile.error.duplicateName", null, locale));
    }
}

On the front-end, I have Angular.js trap the code and then output the error messages (am not presently not using the field names). Below truncated for brevity (full source: JavaScript and JSP):

this.commonErrorResponse = function(response) {   
    self.errorObj = response.data;
}

<div id="errorMessageDiv" class="alert alert-danger" role="alert" ng-show="ctrl.errorObj.errors" ng-cloak>
    <button type="button" class="close" data-ng-click="ctrl.errorObj.errors = null" aria-label="Close">
       <span aria-hidden="true">×</span>
    </button>
    <ul class="list-unstyled">
       <li ng-repeat="item in ctrl.errorObj.errors">{{item.message}}</li>
    </ul>
</div>

Appearance:

400validation

Additionally, I was able to remove a fair amount of per-endpoint boilerplate by creating a single ExceptionHandler for unexpected 500 response code system errors and attaching it to my ControllerAdvice class so it would be used by all REST endpoints. For these types of exceptions usually a generic "System error occurred, please contact Administrator" message is sent to the user. However, I added a UUID that both appears on the client and goes into the logs along with the exception details, making it easy to search the logs for the specific problem. The exception handler (from the TightBlog source):

@ExceptionHandler(value = Exception.class)
// avoiding use of ResponseStatus as it activates Tomcat HTML page (see ResponseStatus JavaDoc)
public ResponseEntity<ValidationErrorResponse> handleException(Exception ex, Locale locale) {
    UUID errorUUID = UUID.randomUUID();
    log.error("Internal Server Error (ID: {}) processing REST call", errorUUID, ex);

    ValidationErrorResponse error = new ValidationErrorResponse();
    error.getErrors().add(new Violation(messages.getMessage(
            "generic.error.check.logs", new Object[] {errorUUID}, locale)));

    return ResponseEntity.status(500).body(error);
}

Screen output:

500errordisplay

Log messaging containing the same UUID:

LogStackTrace

Additional Resources

Posted by Glen Mazza in Programming at 07:00AM Nov 06, 2019 | Comments[0]

https://glenmazza.net/blog/date/20190930 Monday September 30, 2019

TightBlog 3.5.3 Released

Downloads here, deployment instructions here.

Posted by Glen Mazza in Programming at 04:33PM Sep 30, 2019 | Tags:  tightblog | Comments[0]


Calendar
« April 2021
Sun Mon Tue Wed Thu Fri Sat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Today
About Me
Java Software Engineer
TightBlog project maintainer
Arlington, Virginia USA
glen.mazza at pm dot me
GitHub profile for Glen Mazza at Stack Overflow, Q&A for professional and enthusiast programmers
Blog Search


Blog article index
Navigation
About Blog
Blog software: TightBlog 3.7.2
Application Server: Tomcat
Database: MySQL
Hosted on: Linode
SSL Certificate: Let's Encrypt
Installation Instructions