<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://www.chrisweldon.net/feed.xml" rel="self" type="application/atom+xml" /><link href="https://www.chrisweldon.net/" rel="alternate" type="text/html" hreflang="en" /><updated>2021-09-14T18:45:47+00:00</updated><id>https://www.chrisweldon.net/feed.xml</id><title type="html">The Blog of Chris Weldon</title><subtitle>Chris's humble beginnings were in IT Administration and software engineering, but he now manages teams as the Associate Director of Site Reliability Engineering at Wolters Kluwer Tax and Accounting North America. 
</subtitle><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><entry><title type="html">Wood Badge, Scouting, and Leadership</title><link href="https://www.chrisweldon.net/scouting/2021-09-13-wood-badge-leadership-training/" rel="alternate" type="text/html" title="Wood Badge, Scouting, and Leadership" /><published>2021-09-13T00:17:00+00:00</published><updated>2021-09-13T00:17:00+00:00</updated><id>https://www.chrisweldon.net/scouting/wood-badge-leadership-training</id><content type="html" xml:base="https://www.chrisweldon.net/scouting/2021-09-13-wood-badge-leadership-training/">&lt;p&gt;In August 2021, I had the privilege of travelling to &lt;a href=&quot;https://www.philmontscoutranch.org/&quot;&gt;Philmont Scout Ranch&lt;/a&gt; in Cimarron, NM to attend &lt;a href=&quot;https://www.woodbadge133.com/&quot;&gt;Wood Badge 133&lt;/a&gt;. The Wood Badge experience was nothing short of exemplary. I’ve been a scout leader for 5 years and leader and manager of software teams for over 13 years, and I’ve never been to anything quite as comprehensive and well-thought as this leadership training. What was the price for this 5 day training? It’s a steal at under $700!&lt;/p&gt;

&lt;p&gt;The purpose of this blog post is to talk a little about leadership, a little about Scouting, and a &lt;strong&gt;lot&lt;/strong&gt; about Wood Badge.&lt;/p&gt;

&lt;h1 id=&quot;what-is-leadership&quot;&gt;What is leadership?&lt;/h1&gt;
&lt;p&gt;If you ask this question to 5 different people, you’ll likely get 7 different answers. What leadership means is very subjective, but leadership is not just being a manager or a CEO. Everyone is able to lead, regardless of the position they hold in their company (or in scouting).&lt;/p&gt;

&lt;p&gt;To me, leadership is situational. You can be a leader by helping to rally a group of people around a vision, a mission, or a task and see it to completion. You can be a leader by providing coaching or mentoring to people whom need guidance. You can be a leader by helping to bring about change, whether it’s to your team, your office, your company, your school, your community, your nation, or your world. You can be a leader for something small that is very quick, or you can be a leader for initatives that take years. There are so many situations where you can be a leader.&lt;/p&gt;

&lt;p&gt;Most times, chosing to lead is intentional. But sometimes, it’s unintentional. People whom step up to take charge because something must get done can do so without intentionally thinking they are being a “leader”. Are you a volunteer? Guess what - you’re helping to be a leader. You chose to do something without being told. That’s definitely one of the fundamental ways of finding good leaders - finding people with natural drive to want to help and let them soar!&lt;/p&gt;

&lt;h2 id=&quot;what-is-good-leadership&quot;&gt;What is good leadership?&lt;/h2&gt;
&lt;p&gt;Now, just because you step up and take charge of a project doesn’t make you a good or successful leader. It takes a lot to be a really great leader. Great leadership involves:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Defining and measuring success.&lt;/li&gt;
  &lt;li&gt;Understanding the situation and how to navigate the waters.&lt;/li&gt;
  &lt;li&gt;Finding appropriate team members to help you succeed.&lt;/li&gt;
  &lt;li&gt;Communicating effectively with your team and with others (this includes listening).&lt;/li&gt;
  &lt;li&gt;Coaching and mentoring your team to help them succeed.&lt;/li&gt;
  &lt;li&gt;Planning for how to achieve success.&lt;/li&gt;
  &lt;li&gt;Planning for contengencies in case of hypothetical impediments.&lt;/li&gt;
  &lt;li&gt;Driving you and your team to success.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There’s much more to leadership than this above list. Ask another leader and they’ll find probably another half a dozen things to add to my list.&lt;/p&gt;

&lt;p&gt;Being competent in any of these takes time and experience. You won’t always succeed in everything you set out to do. As backwards as this may sound, failure is one of the greatest tools to help a good leader become great. It’s just important not to fail when there are dire consequences!&lt;/p&gt;

&lt;p&gt;The other essential tool to help learn these leadership talents is training. I cannot overstate the importance of leadership training. It helps to provide frameworks, tools, and techniques to help you with various situations. It also provides a safe environment to practice and fail using new tools so you can become comfortable before using them in real life.&lt;/p&gt;

&lt;p&gt;This is why I’m so excited about what Wood Badge leadership training provides to the community.&lt;/p&gt;

&lt;h1 id=&quot;what-is-wood-badge&quot;&gt;What is Wood Badge?&lt;/h1&gt;
&lt;p&gt;&lt;img style=&quot;float: right;&quot; src=&quot;/images/posts/2021-09-13-wood-badge-leadership-training/woodbadge.png&quot; alt=&quot;Wood Badge Logo&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On paper, &lt;a href=&quot;http://woodbadge.org/&quot;&gt;Wood Badge&lt;/a&gt; is the ultimate adult leadership training to help scouting leaders to understand the scouting model and ensure the youth in the program get everything out of the scouting program. At it’s core, Wood Badge is a &lt;em&gt;leaderhip&lt;/em&gt; training course. They teach concepts such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Defining Vision, Mission, and Values&lt;/li&gt;
  &lt;li&gt;How to Understand Yourself to Lead Others&lt;/li&gt;
  &lt;li&gt;Effective Communication and Listening&lt;/li&gt;
  &lt;li&gt;Including and Optimizing Diverse Talent&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://online.stu.edu/articles/education/what-is-situational-leadership.aspx&quot;&gt;Situational Leadership&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.discprofile.com/what-is-disc/&quot;&gt;DiSC Personality Profiles&lt;/a&gt; and how to use them with your team&lt;/li&gt;
  &lt;li&gt;Project Planning with a Bias for Action&lt;/li&gt;
  &lt;li&gt;Coaching and Mentoring&lt;/li&gt;
  &lt;li&gt;Building a Leadership Culture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In total, there are 14 leadership competencies in the Wood Badge curicculum. As you can imagine, there’s not enough time in 5 days to really dive deep into each of these competencies. They give you enough of what you need to know in order to investigate further. However, they do not disappoint in what they are able to present. It is enough for an inexperienced leader to come home with new skills to try and be effective. If they wish to take it further (like with Situational Leadership), additional training exists to help dive deep on any of those topics.&lt;/p&gt;

&lt;p&gt;The Wood Badge training ties these leadership competencies to scouting by using &lt;a href=&quot;https://blog.scoutingmagazine.org/2014/09/05/patrol-method/&quot;&gt;the Patrol Method&lt;/a&gt;. Your patrol is your cohort for the whole of Wood Badge, and you end up forming a good bond with this team.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2021-09-13-wood-badge-leadership-training/Cohort.jpg&quot; alt=&quot;My Cohort - Fox Patrol&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;why-wood-badge-for-leadership-training&quot;&gt;Why Wood Badge for Leadership Training?&lt;/h2&gt;
&lt;p&gt;Part of the reason I loved this training so much was how it told the story of the competencies and how they fit together. Most leadership training I’ve ever been thru has been isolated to one or two competencies. Nothing has ever connected training concepts with one another to help maximize potential. I’ve had to learn how to use each of the concepts and figure out my own path for stitching it together. Wood Badge put us thru grueling, time-limited situations to help us as a patrol see how to effectively use those concepts we just learned to be successful.&lt;/p&gt;

&lt;p&gt;As a leader (scout leader, company leader, or otherwise), you owe it to yourself to get the best training you can that gives you plenty of opportunity to exercise that training in an environment where failure is acceptable and low-risk. Depending on your environment or situation, you don’t often get those opportunities to try to fail (or at least the consequences for failing may be too high).&lt;/p&gt;

&lt;p&gt;If you don’t believe me how inspiring and valuable a training opportunity Wood Badge is, go ask other scouters in your community whom have attended. I have yet to meet a scouter who hasn’t had the same feeling on the importance Wood Badge has been on their life and their relationship to scouting.&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="scouting" /><category term="scouting" /><category term="leadership" /><summary type="html">In August 2021, I had the privilege of travelling to Philmont Scout Ranch in Cimarron, NM to attend Wood Badge 133. The Wood Badge experience was nothing short of exemplary. I’ve been a scout leader for 5 years and leader and manager of software teams for over 13 years, and I’ve never been to anything quite as comprehensive and well-thought as this leadership training. What was the price for this 5 day training? It’s a steal at under $700!</summary></entry><entry><title type="html">Lots of Job Opportunities at Wolters Kluwer</title><link href="https://www.chrisweldon.net/recruiting/2021-04-02-lots-of-new-opportunities-at-wolters-kluwer/" rel="alternate" type="text/html" title="Lots of Job Opportunities at Wolters Kluwer" /><published>2021-04-02T00:18:00+00:00</published><updated>2021-04-02T00:18:00+00:00</updated><id>https://www.chrisweldon.net/recruiting/lots-of-new-opportunities-at-wolters-kluwer</id><content type="html" xml:base="https://www.chrisweldon.net/recruiting/2021-04-02-lots-of-new-opportunities-at-wolters-kluwer/">&lt;p&gt;&lt;strong&gt;Updated September 14, 2021&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the start of 2021, I was asked to lead up a new team within Wolters Kluwer Tax &amp;amp; Accounting. This new team is dubbed the “Always On” engineering team. We are seeking the best and brightest engineers, development managers, and product managers whom are eager for a new opportunity to help dramatically improve the resiliency and performance of our flagship product, &lt;a href=&quot;https://taxna.wolterskluwer.com/professional-tax-software/axcess&quot;&gt;CCH Axcess&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We have positions open in North America:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;North America
    &lt;ul&gt;
      &lt;li&gt;Manager, Product Software Engineering - We are seeking 1 highly technical software engineering manager to help lead our North America team to success.&lt;/li&gt;
      &lt;li&gt;Senior Product Software Engineer - We are seeking one additional senior engineer who has significant experience in either WCF, WPF, Web API, SQL, or any combination of the above.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We also have a ScrumMaster, Product Owner, and Senior or Lead Software Engineer positions still open in India.&lt;/p&gt;

&lt;p&gt;If you’re interested, feel free to hit me up via e-mail at &lt;a href=&quot;mailto:chris@chrisweldon.net&quot;&gt;chris@chrisweldon.net&lt;/a&gt; or ping me on social media. I would love to explain the role and the company and help put your resume into our pipeline!&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="recruiting" /><category term="software" /><summary type="html">Updated September 14, 2021</summary></entry><entry><title type="html">SharePoint REST API Authentication from Java</title><link href="https://www.chrisweldon.net/sharepoint/2016-03-31-sharepoint-rest-api-authentication-from-java/" rel="alternate" type="text/html" title="SharePoint REST API Authentication from Java" /><published>2016-03-31T14:20:59+00:00</published><updated>2016-03-31T14:20:59+00:00</updated><id>https://www.chrisweldon.net/sharepoint/sharepoint-rest-api-authentication-from-java</id><content type="html" xml:base="https://www.chrisweldon.net/sharepoint/2016-03-31-sharepoint-rest-api-authentication-from-java/">&lt;p&gt;Each enterprise has many languages they use to solve their technology problems. C# and Java are the predominate languages used in most enterprises. However, I have noticed a distinct difference between these two types of developers. Enterprises that use Microsoft Active Directory have very little problem with authentication for applications developed using C# (or Visual Basic). &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/aa378749(v=vs.85).aspx&quot;&gt;NTLM&lt;/a&gt; and &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/aa378747(v=vs.85).aspx&quot;&gt;Kerberos&lt;/a&gt; are natively supported for authentication by all .Net applications. Authentication looks like the following (C#):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-c#&quot; data-lang=&quot;c#&quot;&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;HttpClientHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;UseDefaultCredentials&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;client&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Net&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;HttpClient&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; 
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// Make some remote API call&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;It is literally one property to set on most networking libraries. Even when you do not want to use default credentials, there are a rich set of libraries, particularly the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;System.Net.NetworkCredential&lt;/code&gt; class that enables better authentication. Now here is the question: which authentication scheme are you using with this? NTLM, or Kerberos?&lt;/p&gt;

&lt;p&gt;For Java developers, however, the problem was much more complex. I had many Java developers reaching out to me to understand how to properly authenticate to SharePoint. They assumed they had to use NTLM to authenticate to SharePoint. And indeed, the default way web applications are setup for SharePoint is with NTLM. However, many enterprises whom have hybrid Linux and Windows environments need to use Kerberos as their primary authentication system, as Kerberos works far better on Linux than NTLM.&lt;/p&gt;

&lt;p&gt;The purpose of this article is to share how to authenticate Java applications with SharePoint using Kerberos in order to consume SharePoint REST APIs. I did not have extensive experience writing software in Java, much less Java for the enterprise - so these notes may simplify some concepts that are well-known to Java developers. However, if this problem were so easy to solve, why did I have so many Java developers reaching out to me to help them figure out how to solve it?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article assumes the SharePoint environment you are connecting is properly setup for Kerberos authentication. This includes ensuring that the web application is configured for Kerberos authentication, and all &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/windows/desktop/ms677949(v=vs.85).aspx&quot;&gt;SPNs&lt;/a&gt; are properly registered.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional Note:&lt;/strong&gt; For brevity, the code snippets here are greatly simplified and intentionally void of error handling.&lt;/p&gt;

&lt;h2 id=&quot;jumping-to-code&quot;&gt;Jumping to Code&lt;/h2&gt;
&lt;p&gt;I first attempted to understand this problem by writing some code that was meant to just connect to a SharePoint REST service and get data. This is my most basic implementation, which you can see is void of really any authentication details. Keep it simple stupid, right?&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BasicSharePointRestClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ObjectMapper&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ObjectMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BaseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BasicSharePointRestClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Response&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                                   &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json;odata=verbose&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                                   &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;// The request would been unauthorized. httpResponse.getStatusLine().getStatusCode == 401&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;HttpResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;httpResponse&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;returnResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EntityUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;httpResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Needless to say, the above code did not work. At the point where the request was executed, the HTTP response status code would be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HTTP 401 UNAUTHORIZED&lt;/code&gt;, indicating that authentication credentials were &lt;em&gt;not&lt;/em&gt; sent in the originating request.&lt;/p&gt;

&lt;h2 id=&quot;iteration-2&quot;&gt;Iteration 2&lt;/h2&gt;
&lt;p&gt;After further research, I stumbled upon some samples that were posted online. I tinkered with those samples and resulted in the following class. This was my first attempt which &lt;em&gt;really&lt;/em&gt; worked:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpClientForSharePoint&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BasicSharePointRestClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;HttpClientForSharePoint&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;DefaultHttpClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DefaultHttpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getAuthSchemes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthPolicy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SPNEGO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SPNegoSchemeFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;Credentials&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useJaasCredentials&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Credentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getPassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getUserPrincipal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getCredentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCredentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;AuthScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;useJaasCredentials&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;HttpUriRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpGet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json;odata=verbose&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;HttpResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;HttpEntity&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EntityUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I ended up with a proper JSON response (returned as a string) from this. However, there were several things I did not like about this implementation:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get()&lt;/code&gt; had too many responsibilities. It was responsible for configuring authentication as well as executing a REST call.&lt;/li&gt;
  &lt;li&gt;The authentication was limited to only &lt;a href=&quot;https://en.wikipedia.org/wiki/SPNEGO&quot;&gt;SPNEGO&lt;/a&gt;, which is a negotiated authentication mechanism of Kerberos first, falling back to NTLM. What happens if I want to use only Kerberos? Or multiple types of authentication?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;iteration-three&quot;&gt;Iteration Three&lt;/h2&gt;
&lt;p&gt;I continued doing more research and resulted in finding the following, slightly more complex and alternative way to do this. It was derived from the works of the &lt;a href=&quot;https://github.com/spring-projects/spring-security-kerberos/blob/master/spring-security-kerberos-client/src/main/java/org/springframework/security/kerberos/client/KerberosRestTemplate.java&quot;&gt;Spring Security Kerberos Client&lt;/a&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-java&quot; data-lang=&quot;java&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BuilderSharePointRestClient&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BasicSharePointRestClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BuilderSharePointRestClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;baseUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;LoginContext&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoginContext&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;SharePoint&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TextCallbackHandler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;lc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Subject&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;serviceSubject&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSubject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Subject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;doAs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;serviceSubject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PrivilegedAction&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nc&quot;&gt;HttpClient&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getHttpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;HttpUriRequest&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpGet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BaseUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Accept&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;application/json;odata=verbose&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;HttpResponse&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;httpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;execute&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;HttpEntity&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getEntity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;EntityUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;nc&quot;&gt;EntityUtils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;consume&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;entity&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;results&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;});&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpClient&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getHttpClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;HttpClientBuilder&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;HttpClientBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Lookup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthSchemeProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;authSchemeRegistry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RegistryBuilder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthSchemeProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthSchemes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;KERBEROS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;KerberosSchemeFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthSchemes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;NTLM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NTLMSchemeFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;AuthSchemes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SPNEGO&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SPNegoSchemeFactory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setDefaultAuthSchemeRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;authSchemeRegistry&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;Credentials&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useJaasCredentials&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Credentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getPassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Principal&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getUserPrincipal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;};&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;BasicCredentialsProvider&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;credentialsProvider&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BasicCredentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;credentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setCredentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;AuthScope&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useJaasCredentials&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;setDefaultCredentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;credentialsProvider&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;builder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The above class worked like a charm, and provided the best of single responsibility (although the private method should be moved to a different class), but nevertheless simplified the responsibilities of each method.&lt;/p&gt;

&lt;h1 id=&quot;configuring-java-how-to-authenticate-using-kerberos&quot;&gt;Configuring Java How to Authenticate Using Kerberos&lt;/h1&gt;
&lt;p&gt;Authentication in Java is performed by the &lt;a href=&quot;http://docs.oracle.com/javase/7/docs/technotes/guides/security/jaas/JAASRefGuide.html&quot;&gt;Java Authentication and Authorization Service (JAAS)&lt;/a&gt;. JAAS has a number of “defaults” that it uses when attempting to perform authentication, including Kerberos. We need to get an understanding of how Java authenticates using Kerberos within your corporate environment. This is dictated by two files, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login.conf&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krb5.conf&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;First, let us look at the &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/technotes/guides/security/jgss/tutorials/LoginConfigFile.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login.conf&lt;/code&gt; file&lt;/a&gt;. From what I can tell, this file has no default “global” configuration, so you will need to create it from scratch. It has the following format:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;&amp;lt;packagename.entryclass&amp;gt; {
    &amp;lt;loginmodule&amp;gt; &amp;lt;flags&amp;gt; &amp;lt;loginmodule options&amp;gt;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The following is my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;login.conf&lt;/code&gt; for the classes above (and classes I depend upon). It may be overkill, but it works:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;com.sun.security.jgss.login {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
com.sun.security.jgss.initiate {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
com.sun.security.jgss.accept {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
net.chrisweldon.SharePoint.BasicSharePointRestClient {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
net.chrisweldon.SharePoint.HttpClientForSharePoint {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};
net.chrisweldon.SharePoint.BuilderSharePointRestClient {
    com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;
};&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The second file is the &lt;a href=&quot;http://web.mit.edu/kerberos/krb5-1.13/doc/admin/conf_files/krb5_conf.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krb5.conf&lt;/code&gt; file&lt;/a&gt;. This file is the kerberos configuration file, which tells what domains and realms are supported for authentication via Kerberos. The documentation (and purpose) of this file can get fairly complex given the corporate environment. However, if yours is setup correctly, you may not need to make any changes.&lt;/p&gt;

&lt;p&gt;The default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krb5.conf&lt;/code&gt; file is located at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%JAVA_HOME%\lib\security\krb5.conf&lt;/code&gt;. If you open it up, it may look like the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[libdefaults]
    default_realm = CORP.CHRISWELDON.NET

[domain_realm]
    .corp.chrisweldon.net = CORP.CHRISWELDON.NET
    .othercorp.chrisweldon.net = OTHER.CHRISWELDON.NET

[realms]
    CORP.CHRISWELDON.NET = {
        dns_lookup_realm = true
        dns_lookup_kdc = true
        kdc = KDC.CHRISWELDON.NET
    }

    OTHER.CHRISWELDON.NET = {
        dns_lookup_realm = true
        dns_lookup_kdc = true
        kdc = OTHERKDC.CHRISWELDON.NET
    }&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;What this means is if I try to authenticate to a host that has a domain suffix of either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.corp.chrisweldon.net&lt;/code&gt; (e.g &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sharepoint.corp.chrisweldon.net&lt;/code&gt;) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.othercorp.chrisweldon.net&lt;/code&gt; (e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exchange.othercorp.chrisweldon.net&lt;/code&gt;), Kerberos libraries will know what KDC servers to perform the authentication against.&lt;/p&gt;

&lt;p&gt;Now, suppose you have a machine that is in your enterprise, but has an alias for a different domain, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sharepoint.chrisweldon.com&lt;/code&gt;. Even if that server is connected to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CORP.CHRISWELDON.NET&lt;/code&gt; domain in Active Directory, the fact that you have an alias not listed in your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krb5.conf&lt;/code&gt; file will cause you issues. So, copy the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;krb5.conf&lt;/code&gt; file to your project directory and edit it to look like the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;[libdefaults]
    default_realm = CORP.CHRISWELDON.NET

[domain_realm]
    .corp.chrisweldon.net = CORP.CHRISWELDON.NET
    .othercorp.chrisweldon.net = OTHER.CHRISWELDON.NET
    .chrisweldon.com = CORP.CHRISWELDON.NET # this is the addition

[realms]
    CORP.CHRISWELDON.NET = {
        dns_lookup_realm = true
        dns_lookup_kdc = true
        kdc = KDC.CHRISWELDON.NET
    }

    OTHER.CHRISWELDON.NET = {
        dns_lookup_realm = true
        dns_lookup_kdc = true
        kdc = OTHERKDC.CHRISWELDON.NET
    }&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;You are ready to execute your Java application! Simply specify the following arguments to ensure your app is looking at your custom configuration files and it will be authenticating to SharePoint!&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;-Djava.security.krb5.conf=C:/path/to/custom/krb5.conf -Djavax.security.auth.useSubjectCredsOnly=false -Djava.security.auth.login.config=C:/path/to/custom/login.conf&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="SharePoint" /><category term="sharepoint" /><category term="rest" /><category term="authentication" /><category term="java" /><category term="kerberos" /><summary type="html">Each enterprise has many languages they use to solve their technology problems. C# and Java are the predominate languages used in most enterprises. However, I have noticed a distinct difference between these two types of developers. Enterprises that use Microsoft Active Directory have very little problem with authentication for applications developed using C# (or Visual Basic). NTLM and Kerberos are natively supported for authentication by all .Net applications. Authentication looks like the following (C#):</summary></entry><entry><title type="html">Finding When a User First Got Access to a SharePoint Site via REST</title><link href="https://www.chrisweldon.net/sharepoint/2016-02-03-finding-when-a-user-first-got-access-to-a-sharepoint-site-via-rest/" rel="alternate" type="text/html" title="Finding When a User First Got Access to a SharePoint Site via REST" /><published>2016-02-03T14:20:59+00:00</published><updated>2016-02-03T14:20:59+00:00</updated><id>https://www.chrisweldon.net/sharepoint/finding-when-a-user-first-got-access-to-a-sharepoint-site-via-rest</id><content type="html" xml:base="https://www.chrisweldon.net/sharepoint/2016-02-03-finding-when-a-user-first-got-access-to-a-sharepoint-site-via-rest/">&lt;p&gt;I have experienced many legacy solutions which closely depend on the SharePoint Server Side Object Model (SSOM). This was the only option for being able to manage your SharePoint 2007 and 2010 farms. You may have read on some of my past blog posts, code written against the SharePoint SSOM is extremely difficult to unit test without &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/hh549175.aspx?f=255&amp;amp;MSPPError=-2147217396&quot;&gt;Microsoft Fakes&lt;/a&gt; or writing a facade. As a result, I have deepened my familiarity with the SharePoint 2013 REST APIs. They are much more strategic, especially when planning for the possibility of moving to SharePoint Online / Office 365.&lt;/p&gt;

&lt;p&gt;While working on permissions management within SharePoint, I needed to identify when a user first obtained access to their SharePoint 2013 site. I typically look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiteUsers&lt;/code&gt; table for information relating to users against a Site Collection. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiteUsers&lt;/code&gt; collection can be accessed via the SharePoint REST API by going to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/_api/web/SiteUsers&lt;/code&gt;. However, the properties on each &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiteUser&lt;/code&gt; look like the following (obtained from the &lt;a href=&quot;https://msdn.microsoft.com/en-us/library/office/dn531432.aspx#bk_UserCollection&quot;&gt;Users, groups, and roles REST API Reference&lt;/a&gt;):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/GetUserById(16)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/GetUserById(16)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SP.User&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Groups&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__deferred&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/GetUserById(16)/Groups&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;IsHiddenInUI&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;LoginName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;i:0#.w|domain&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\\&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;user1&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Title&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot; User1 Display Name &quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;PrincipalType&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Email&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;user1@company.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;IsSiteAdmin&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SP.UserIdInfo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;NameId&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;s-0-0-00-000000-0000000000-0000000000-000000&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;NameIdIssuer&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;issuer id&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
      &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
  &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;There are no dates in this. When I thought about it, I remembered the &lt;a href=&quot;http://zimmergren.net/technical/sharepoints-hidden-user-list-user-information-list&quot;&gt;User Information List&lt;/a&gt;. This list contains a wealth of additional details beyond what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SiteUsers&lt;/code&gt; collection provides. The reason: it is nothing more than a list - just one with &lt;em&gt;lots&lt;/em&gt; of columns of rich data. More importantly, it is available to query via the REST API! Checking the structure of the User Information List was as simple as executing the following REST query:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;GET /_api/web/lists/getbytitle('User Information List')/Fields?$select=InternalName&amp;amp;$filter=InternalName%20eq%20'Created'%20or%20InternalName%20eq%20'UserName'
Accept: application/json;odata=verbose&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; a short way is via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/_api/web/SiteUserInfoList&lt;/code&gt;. The results are as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/SiteUserInfoList/Fields(guid'453160d6-6a28-42ba-ba45-9f9d2c70407d')&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/SiteUserInfoList/Fields(guid'453160d6-6a28-42ba-ba45-9f9d2c70407d')&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SP.FieldText&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;InternalName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;UserName&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/SiteUserInfoList/Fields(guid'8c06beca-0777-48f7-91c7-6da68bc07b69')&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/SiteUserInfoList/Fields(guid'8c06beca-0777-48f7-91c7-6da68bc07b69')&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SP.FieldDateTime&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;InternalName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;Created&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Awesome! It exists! Now all I have to do is query for the specific user that I want. When I have a specific UserName to find, all I have to execute is the following query:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;GET /_api/web/SiteUserInfoList/Items?$select=UserName,Created&amp;amp;$filter=UserName%20eq%20'neraath@chrisweldon.onmicrosoft.com'
Accept: application/json;odata=verbose&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;And I get exactly what I want:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-json&quot; data-lang=&quot;json&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;d&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;results&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;__metadata&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;7df6fc9b-0755-421e-934d-617ca89d5d9f&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;uri&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;https://chrisweldon.sharepoint.com/_api/Web/SiteUserInfoList/Items(12)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;etag&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;type&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;SP.Data.UserInfoItem&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;UserName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;neraath@chrisweldon.onmicrosoft.com&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
                &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;Created&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;2013-04-12T15:38:12Z&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;In summary, when you are looking to find information about users whom have access to your SharePoint sites, remember the User Information List, and also remember it is queryable via the REST API!&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="SharePoint" /><category term="sharepoint" /><category term="rest" /><category term="user information list" /><category term="uil" /><summary type="html">I have experienced many legacy solutions which closely depend on the SharePoint Server Side Object Model (SSOM). This was the only option for being able to manage your SharePoint 2007 and 2010 farms. You may have read on some of my past blog posts, code written against the SharePoint SSOM is extremely difficult to unit test without Microsoft Fakes or writing a facade. As a result, I have deepened my familiarity with the SharePoint 2013 REST APIs. They are much more strategic, especially when planning for the possibility of moving to SharePoint Online / Office 365.</summary></entry><entry><title type="html">On Helpers and the use of static</title><link href="https://www.chrisweldon.net/software%20development/2014-03-03-on-helpers-and-the-use-of-static/" rel="alternate" type="text/html" title="On Helpers and the use of static" /><published>2014-03-03T05:08:21+00:00</published><updated>2014-03-03T05:08:21+00:00</updated><id>https://www.chrisweldon.net/software%20development/on-helpers-and-the-use-of-static</id><content type="html" xml:base="https://www.chrisweldon.net/software%20development/2014-03-03-on-helpers-and-the-use-of-static/">&lt;p&gt;One of my most recent interactions with several of my colleagues has been over best practices within software development. More specifically, the idea of static classes, static methods, and helper classes. It was a healthy debate with different view points. Some believe that static methods are perfectly fine for development. Others feel that helper classes provide unity to certain practices such as database access. Generally, however, I believe static and helper classes are an anti-pattern and lead to less maintainable code. This post is an expression of why I believe this to be the case. None of the code samples are actual snippets on real projects. They are paraphrased instances of practices I’ve seen on a myriad of past projects.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id=&quot;so-why-are-statics-bad&quot;&gt;So, why are statics bad?&lt;/h2&gt;
&lt;p&gt;I’m a huge fan of automated testing. I started with unit tests, but have recently moved into the realm of behavior tests. Yet, for any automated testing, you have to have good architecture in your code to ensure that you &lt;em&gt;can&lt;/em&gt; test in any environment.&lt;/p&gt;

&lt;p&gt;Let me give the most basic example: the use of a logging facility. Take for example the following loggger that I see all too often:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;LoggingHelper&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LogMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LogPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AppendText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;INFO\t[&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;]&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LogError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LogPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AppendText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;ERROR\t[&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;]&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;LogException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Constants&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LogPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamWriter&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AppendText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;EXCEPTION\t[&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;area&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;]&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot; - &quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Stack Trace&quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StackTrace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Here are a few areas the above code block can improve:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;There’s no exception handling. At all.&lt;/li&gt;
  &lt;li&gt;There’s no mutexes/resource locking. Thus, it’s possible for multiple threads to attempt to open the file at the same time. The first one in will succeed. All others will throw exceptions.&lt;/li&gt;
  &lt;li&gt;It’s insanely duplicative. In fact, I was able to copy every line of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogMessage&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogError&lt;/code&gt; and only have to change 2 lines of code. The same goes for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogException&lt;/code&gt;, where I also added an additional line.&lt;/li&gt;
  &lt;li&gt;What happens when I have another type of message I need to log? That means I must add another method - 6 of those lines likely the same as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LogMessage&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;What happens when I need to change the location of the log file?&lt;/li&gt;
  &lt;li&gt;What happens when I need to change the underlying facility for logging? Say, from files to databases?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last two are key here. For the first, I can change from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Constants.LogPath&lt;/code&gt; to something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ConfigurationManager.AppSettings[&quot;LogPath&quot;]&lt;/code&gt;, But what happens when the file is a network file system? Not accessible via standard UNC paths? You’re up a creek and this &lt;em&gt;entire class&lt;/em&gt; needs to change. That’s pretty much the case of the second question.&lt;/p&gt;

&lt;p&gt;You should assume that your underlying logging destination can &lt;strong&gt;and will&lt;/strong&gt; change at any time. If you think that the simple solution to this is to simply change the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoggingHelper&lt;/code&gt; class, think again. Let’s take this further. You should assume that your destination will be different for &lt;strong&gt;multiple scenarios&lt;/strong&gt;. In enterprise development, this is frequently the case. In a pre-integration environment, you may only want to log to the filesystem because it may be a single server. However, in integration and production you might choose to log to a database since you’re deploying to a farm of servers and writing to the filesystem makes diagnosing problems a true headache.&lt;/p&gt;

&lt;p&gt;Back to the problem of automated testing, you don’t really want any logging. Why? What happens when your test runner doesn’t have access to the logging path? What happens when your test environment doesn’t have the path at all? What happens when you forget you have your test environment dumping massive amounts of logs to the filesystem only to go on a goose chase figuring out why your builds randomly started to fail due to the disk being full? In the case of unit testing, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/dev/null&lt;/code&gt; should be your destination.&lt;/p&gt;

&lt;p&gt;Let’s consider one last secenario: what happens if you want to log to multiple facilities at once?&lt;/p&gt;

&lt;p&gt;In any of those cases, using a static class with static methods does not afford you &lt;strong&gt;any&lt;/strong&gt; flexibility. If you want to expand to multiple logging facilities, you would be forced to create another static class. That class is now called in addition to this one. Yuck.&lt;/p&gt;

&lt;p&gt;Here’s where I come back to the &lt;a href=&quot;3&quot;&gt;SOLID principles&lt;/a&gt;. Let’s look at how Static classes (and static methods) violate these principles.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open/Closed Principle - Classes should be open for extension, but closed for modification.
    &lt;ul&gt;
      &lt;li&gt;With statics, you &lt;strong&gt;cannot&lt;/strong&gt; extend and override the behavior. You throw out the idea of polymorphism. This makes it &lt;del&gt;very difficult&lt;/del&gt; impossible for me to inject different behaviors for whatever need I may have.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Dependency Inversion Principle - Depend upon Abstractions. Do not depend upon concretions.
    &lt;ul&gt;
      &lt;li&gt;With statics, every class that leverages its facilities are now dependent upon a concretion. There is no way to pass around an abstraction of a static class or regular class with static methods. Your only way of doing this is with reflection and that’s a definite code smell.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In summary, because I cannot leverage the power of inheritance, polymorphism, or really any aspect of object oriented analysis and design with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;statics&lt;/code&gt;, it feels a lot like procedural programming. I suggest leaving this practice behind.&lt;/p&gt;

&lt;h2 id=&quot;so-why-are-helpers-bad&quot;&gt;So, why are helpers bad?&lt;/h2&gt;
&lt;p&gt;My discussion with my colleagues yielded an interesting observation: everyone’s opinion of a helper was slightly different. One thought of it as a single data access layer. Another thought of it as a way of providing consistent authentication for data access. But others think of helpers as the giant “I don’t know where to stick this method” bucket. So, you end up with something like this (methods only, since that should convey what I’m getting at):&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Utils&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CleanInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;FlushCacheIndex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CheckIfSystemIsHealthy&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetCountOfActiveUsers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyModel&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateModelFromInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;age&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DateTime&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;birthday&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;These types of helpers are a maintainability nightmare. For starters, if you haven’t read my section above on why statics are bad, step back and read it. Both SOLID principles are still violated. Yet, there are also a couple of others that are violated.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Single Responsibility Principle - A class should have only one reason to change.
    &lt;ul&gt;
      &lt;li&gt;It’s clear in the case above that there are multiple reasons this class exists. However, there are other helper classes (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;StringUtils&lt;/code&gt; which are not as clear. However, I’m still a firm believer that the Open/Closed Principle dictates whether to add yet another method to an existing class, or create a separate class. I’m a huge fan of small classes as their much easier to test and maintain.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Interface Segregation Principle - Many client-specific interfaces are better than one general-purpose interface.
    &lt;ul&gt;
      &lt;li&gt;Okay, so this isn’t an interface. ISP is definitely meant for solving another problem. However, the basics behind this principle apply here. This is a general-purpose class. Why should I have my code &lt;strong&gt;strongly-coupled&lt;/strong&gt; to this class if all I need is one method within it?&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, to tackle some of the other arguments in favor of helper classes, let’s look at another example I’ve seen in the past:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DatabaseHelper&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataAccessObject&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daoInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DataAccessObject&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateDataAccessObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokingUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;daoInstance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DataAccessObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AuthenticationMode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AuthenticationModes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Shared&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Credentials&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;DataAccessCredentials&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;invokingUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Kerberos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokingUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dao&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;daoInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Ah, rather than a helper, you meant a factory. Okay, I can dig that…sorta. We’re still using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;static&lt;/code&gt; here, which makes it impossible for me to factorize the creation of my DAO without strongly coupling my business logic to this &lt;em&gt;specific&lt;/em&gt; class. Now, a factory is meant to abstract away the details of creating an object of a specific type. There’s some generally common expected inputs, and you get a generic implementation at the output. But, how should you go about doing that?&lt;/p&gt;

&lt;p&gt;If you’re using a proper dependency injection/Inversion of Control container, you’ll be able to configure your application instance to inject a provider which implements the following interface:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DataAccessFactory&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;DataAccessObject&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CreateDataAccessObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;User&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;invokingUser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Furthermore, if you’re in a spot where you need a singleton instance of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataAccessObject&lt;/code&gt;, then you can make sure that you implement the appropriate logic in your Factory instance &lt;strong&gt;and&lt;/strong&gt; setup your IoC container to maintain a singleton instance of the object.&lt;/p&gt;

&lt;p&gt;When discussing the use of “helper” classes, it’s more difficult to outright say they aren’t useful, because each person’s definition of helper classes are different. Nevertheless, if you venture down the path of bucket “utility” classes, stop. There are better approaches you can take.&lt;/p&gt;

&lt;h2 id=&quot;well-i-still-dont-agree-with-you&quot;&gt;Well, I still don’t agree with you…&lt;/h2&gt;
&lt;p&gt;That’s fine. You’re entitled to your opinion. Just don’t expect for me to pass your code reviews.&lt;/p&gt;

&lt;p&gt;Are there circumstances where the use of a static method might be worth it? Quite possibly. But I rarely encounter those cases. If one of those reasons is “it’s faster to do it with a static than via good architecture” then you’re just being lazy. Yes, software development is about delivering value. However, what debt you introduce to the system must later be addressed save you be unable to deliver any value once you’ve built a castle with no doors &lt;strong&gt;around you&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’m not alone in this. Check out just a few other blogs which carry several really good arguments against the use of statics or helpers:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://lostechies.com/chrismissal/2009/06/01/anti-patterns-and-worst-practices-utils-class/&quot;&gt;Anti-patterns and Worst Practices - Utils Classes&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://oo-programming.blogspot.com/2009/06/util-classes-must-die.html&quot;&gt;Util Classes Must Die&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blogs.msdn.com/b/nickmalik/archive/2005/09/06/461404.aspx&quot;&gt;Are Helper Classes Evil?&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://blogs.msdn.com/b/elee/archive/2009/05/05/helper-classes-are-evil.aspx&quot;&gt;Helper Classes are Evil&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;where-did-you-shape-your-thoughts-on-best-practices&quot;&gt;Where did you shape your thoughts on best practices?&lt;/h2&gt;
&lt;p&gt;In my previous role at &lt;a href=&quot;2&quot;&gt;Improving Enterprises&lt;/a&gt;, there were a number of really talented technologists, passionate about best practices. They were staunch supporters of user groups and community as well. Thus, my opinions on best practices have been shaped not only through previous co-workers and colleagues, but also by community.&lt;/p&gt;

&lt;p&gt;Community has a lot of benefits, and has a lot of diversity of thought. The software community provides an atmosphere for technologists to actively try many of the best practices they preach through katas, discussions, pull requests, and many other channels. These best practices are most commonly focused around the use of patterns. Why reinvent the wheel when patterns exist to help solve the same or similar problems? However, these patterns often have justifiable use: they leverage the facets of object oriented languages in the manner they were &lt;em&gt;expected&lt;/em&gt; to be used.&lt;/p&gt;

&lt;p&gt;This is where I started to learn about best practices. My source of community was extremely diverse. It included my colleagues at work, my close developer friends, and those technologists in the community who were extremely passionate about their work. Some of these technologists I engaged only through user groups, some through their blogs, and some through discussion boards. I am a high achiever, and in order for me to achieve, I must learn - so I am always on a continuous search for new information - even if it contradicts previous thoughts or practices I held imporant to me.&lt;/p&gt;

&lt;p&gt;Finally, the only other way to really learn and solidify the importance of a best practice is to, well, &lt;strong&gt;practice&lt;/strong&gt; it. With enough practice, you’ll invariably run into other practices which box you into a corner or make your life &lt;em&gt;very&lt;/em&gt; difficult. The more times you encounter these situations, the greater a believer in best practices which leverage the power of object oriented design and development.&lt;/p&gt;

&lt;p&gt;Diversity of thought is a great practice and should be encouraged. It leads to more out-of-the-box thinking, approaches to problems, and ensures that all risks are vocalized. However, one of the most important things I’ve had to learn is that no matter what, diversity of thought should always be supported with sound reason and justification. Simply citing a preference to a mode of practice, idea, or solution without good justification to a practice is hard to accept in a professional setting.&lt;/p&gt;

&lt;p&gt;[2] http://www.improvingenterprises.com/
  [3] http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="software development" /><category term="software" /><category term="development" /><category term="programming" /><category term="best practices" /><summary type="html">One of my most recent interactions with several of my colleagues has been over best practices within software development. More specifically, the idea of static classes, static methods, and helper classes. It was a healthy debate with different view points. Some believe that static methods are perfectly fine for development. Others feel that helper classes provide unity to certain practices such as database access. Generally, however, I believe static and helper classes are an anti-pattern and lead to less maintainable code. This post is an expression of why I believe this to be the case. None of the code samples are actual snippets on real projects. They are paraphrased instances of practices I’ve seen on a myriad of past projects.</summary></entry><entry><title type="html">Communication Brevity</title><link href="https://www.chrisweldon.net/systems%20administration/2013-11-26-brevity/" rel="alternate" type="text/html" title="Communication Brevity" /><published>2013-11-26T18:50:00+00:00</published><updated>2013-11-26T18:50:00+00:00</updated><id>https://www.chrisweldon.net/systems%20administration/brevity</id><content type="html" xml:base="https://www.chrisweldon.net/systems%20administration/2013-11-26-brevity/">&lt;p&gt;Let’s talk about something I really don’t like: e-mail. Let me clarify this by saying I &lt;em&gt;loathe&lt;/em&gt; e-mails on &lt;strong&gt;team&lt;/strong&gt; projects. Why? Persistence. Conversations via e-mail have this perception they will be “found” at a later time, but the proposed value is rarely so useful. Furthermore, new team members or collaborators &lt;em&gt;rarely&lt;/em&gt; ever get that context, because it’s buried in &lt;strong&gt;another&lt;/strong&gt; person’s e-mail. This is my approach to how teams should communicate to ensure longevity of this critically important information.
&lt;!--more--&gt;
I’m a huge fan of the &lt;a href=&quot;http://blogs.atlassian.com/2009/01/2009_email_brev/&quot;&gt;e-mail brevity challenge&lt;/a&gt;. The idea is simple: keep your e-mails short. 140 characters short. What this limits you to do is &lt;strong&gt;huge&lt;/strong&gt;. Do you think you can have technical design discussions with 140 characters? What about researching technical support problems? How about product feature ideas? Clarifying how your team came to the conclusion to disable a feature due to security constraints? You might be able to do this in a bunch of 140 character e-mails, but that’s hardly a good use of time.&lt;/p&gt;

&lt;h1 id=&quot;the-problem&quot;&gt;The Problem&lt;/h1&gt;
&lt;p&gt;For those examples I listed above, how important is it to your team to find that information now or three years from now? Let’s face it - most teams undergo turnover at some point and with some degree of variability. Those whom are left find themselves struggling to find the context - the &lt;em&gt;why&lt;/em&gt; - beind a particular decision. This becomes more evident the longer time passes since a decision was made.&lt;/p&gt;

&lt;p&gt;We have this problem now. I am considering simplifying a system we have currently. Yet, I can’t find any context to understand why the system is currently so complex. Everyone agrees there &lt;strong&gt;should&lt;/strong&gt; be a reason, but nobody knows &lt;em&gt;why&lt;/em&gt; that reason is. The &lt;strong&gt;how&lt;/strong&gt; of the system was perfectly documented, but the &lt;em&gt;why&lt;/em&gt; was not. If current (and former) history are any sign, it’s likely the conversation of &lt;em&gt;why&lt;/em&gt; has been lost somewhere along the way.&lt;/p&gt;

&lt;h1 id=&quot;the-solution&quot;&gt;The Solution&lt;/h1&gt;
&lt;p&gt;As previously indicated, expressing yourself via e-mail in 140 characters or less is hard. You want to know what isn’t hard to express under that constraint? A URL.&lt;/p&gt;

&lt;p&gt;The solution to this problem is easy. If you shift your conversation online, its longevity or persistance is no longer tied to the life of someone’s inbox. We have what we call a “posting” culture at the firm - a process to keep as many people who are directly involved or &lt;em&gt;may&lt;/em&gt; be involved informed about the progress of our work. However, doing so via e-mail is laborious, especially if you leave out a stakeholder. However, if the conversation is non-private, having that conversation on an online social platform enables those stakeholders to opt-in to your updates. They can sit on the sidelines watching the activity, or if they see something that requires their intervention, they can take charge and engage in the conversation.&lt;/p&gt;

&lt;p&gt;But what about private conversations? Most social platforms have the capability for engaging in private conversation. Whether this be through closed collaboration/team rooms or direct messages between you and another user. However, once decisions have been made, it becomes easy to promote the relevant pieces of those conversations from private to public - it’s already online.&lt;/p&gt;

&lt;h1 id=&quot;additional-benefits&quot;&gt;Additional Benefits&lt;/h1&gt;
&lt;p&gt;The problems of traditional e-mail go beyond simply lack of context. Many corporate e-mail platforms &lt;strong&gt;still&lt;/strong&gt; don’t provide metadata tagging. Searching for e-mail means you search conversations only &lt;em&gt;you&lt;/em&gt; were directly involved. Being able to keep track of the conversation thread is dismal with our tools - only a few e-mail clients (and only very recently) are able to present conversations in threaded views. Most people &lt;strong&gt;still&lt;/strong&gt; don’t know those features exist! Finally, collboration on documents still happens by shipping them via e-mail. Which is the authoritative &lt;em&gt;final&lt;/em&gt; version? Finally, what &lt;strong&gt;was&lt;/strong&gt; the final decision of that chain of e-mails about how to proceed on our design?&lt;/p&gt;

&lt;p&gt;Moving the conversation online to social platforms opens up many other benefits. Tagging (primarily #tags, pronounced as hashtags) are in most platforms. For those not familiar, tagging content with certain keywords enables easier discoverability. When you search for relevant conversations using those keywords, the search engine considers tagged posts more relevant than posts having those words somewhere in the document. A human made the decision that keyword pertains to this conversation, rather than that word being used in a conversation about something completely different. Search is also enhanced as you’re now searching all &lt;em&gt;open&lt;/em&gt; and &lt;strong&gt;public&lt;/strong&gt; conversations, broadening your search potential.&lt;/p&gt;

&lt;p&gt;Being able to follow conversations is much easier. Threaded views enable clear visibility and understanding of the flow of conversations. Furthermore, most social platforms (especially in the Q&amp;amp;A space) have options for marking something as a “correct” or “most helpful” answer. Leveraging these same features, even for team discussions accomplishes two things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You know exactly which decision was made, even when the content indicating that a decision had been made was unclear.&lt;/li&gt;
  &lt;li&gt;You have all of the conversation surrounding why that decision was made.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, when it comes to sharing and collaborating on content, like Word/Excel/PowerPoint documents, moving that online and providing a &lt;em&gt;single&lt;/em&gt; authoritative source for the document reduces confusion on which is the final version and the final copy.&lt;/p&gt;

&lt;h1 id=&quot;give-it-a-try&quot;&gt;Give it a Try&lt;/h1&gt;
&lt;p&gt;Don’t wait. Force yourself into this model. It will be hard - you’ll want to revert back to your old ways of typing lengthy e-mails and using distribution lists. When you find yourself writing even just &lt;strong&gt;two&lt;/strong&gt; sentences in an e-mail: stop. Immediately move to your online space and continue. Don’t be tempted to reply in e-mail to someone sending you the link to the topic thread they started online - keep the conversation where it originated! But move it online if it started in e-mail!&lt;/p&gt;

&lt;p&gt;While your team starts adopting this pattern of communication, you’ll see some short-term gains (like discoverability, transparency, clarity of decisions, inclusion, etc.). However, this is all about the long-term gains your team will have. The more content you push online, the better it will be for your team when it comes to retaining critical information. It &lt;em&gt;will&lt;/em&gt; be worth it!&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="systems administration" /><category term="sharepoint" /><category term="enterprise" /><category term="social" /><category term="brevity" /><category term="communication" /><category term="email" /><category term="technology" /><summary type="html">Let’s talk about something I really don’t like: e-mail. Let me clarify this by saying I loathe e-mails on team projects. Why? Persistence. Conversations via e-mail have this perception they will be “found” at a later time, but the proposed value is rarely so useful. Furthermore, new team members or collaborators rarely ever get that context, because it’s buried in another person’s e-mail. This is my approach to how teams should communicate to ensure longevity of this critically important information. I’m a huge fan of the e-mail brevity challenge. The idea is simple: keep your e-mails short. 140 characters short. What this limits you to do is huge. Do you think you can have technical design discussions with 140 characters? What about researching technical support problems? How about product feature ideas? Clarifying how your team came to the conclusion to disable a feature due to security constraints? You might be able to do this in a bunch of 140 character e-mails, but that’s hardly a good use of time.</summary></entry><entry><title type="html">SharePoint 2013 My Site Timer Jobs Missing</title><link href="https://www.chrisweldon.net/systems%20administration/software%20development/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/" rel="alternate" type="text/html" title="SharePoint 2013 My Site Timer Jobs Missing" /><published>2013-08-02T15:07:00+00:00</published><updated>2013-08-02T15:07:00+00:00</updated><id>https://www.chrisweldon.net/systems%20administration/software%20development/sharepoint-2013-my-site-timer-jobs-missing</id><content type="html" xml:base="https://www.chrisweldon.net/systems%20administration/software%20development/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/">&lt;p&gt;The way My Sites are created in SharePoint 2013 is vastly different from SharePoint 2010, but for good reason. I won’t go into the details of how it’s changed, as Wictor Wilen has done an &lt;em&gt;excellent&lt;/em&gt; job of this already in his blog post &lt;a href=&quot;http://www.wictorwilen.se/sharepoint-2013-personal-site-instantiation-queues-and-bad-throughput&quot;&gt;SharePoint 2013: Personal Site Instantiation Queues and Bad Throughput&lt;/a&gt;. I encountered problems with a new development workstation not setting up My Sites for users appropriately - blocking us from testing our solution, which was dependent upon a user having a My Site. In looking online (and in Wictor’s blog post), everything was pointing to checking the following three timer jobs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;My Site Instantiation Interactive Request Queue&lt;/li&gt;
  &lt;li&gt;My Site Instantiation Non-Interactive Request Queue&lt;/li&gt;
  &lt;li&gt;My Site Second Instantiation Interactive Request Queue&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem is, those timer jobs were missing from my server!
&lt;!--more--&gt;
I checked for the timer jobs first through Central Administration, and then subsequently thru PowerShell. The following are the results I found:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Get-SPTimerJob | sort Name | ft Name
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/01-missing-timerjobs.png&quot; alt=&quot;Timer Jobs Missing&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I decided to check for the My Site timer jobs on a know working SharePoint 2013 farm. Sure enough, they were there:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/02-present-timerjobs.png&quot; alt=&quot;Timer Jobs Present on Farm&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I wanted to look for a way to re-register timer jobs. There should be no reason for me to do something drastic like uninstall/reinstall the User Profile Service just to get the timer job re-registered. This timer job, as expected, was in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Microsoft.Office.Server.UserProfiles&lt;/code&gt; assembly:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/03-timerjob-definition.png&quot; alt=&quot;Timer Jobs Definition&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, I cracked open dotPeek and decided to hunt for that timer job definition and find who was using it. It turns out, there’s a web application-level feature (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MySiteInstantiationQueuesFeatureReceiver&lt;/code&gt;) which registers these timer jobs:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/04-featurereceiver.png&quot; alt=&quot;Timer Job Feature&quot; /&gt;&lt;/p&gt;

&lt;p&gt;There is a public static method inside that feature receiver used for registering the timer jobs.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/05-methodtoregistertimerjobs.png&quot; alt=&quot;Method to Register Timer Jobs&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So, I had one of two options: invoke the static method directly, or simply toggle the feature. I opted to toggle the feature:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$feat = Get-SPFeature 65B53AAF-4754-46D7-BB5B-7ED4CF5564E1
Disable-SPFeature $feat -Url http://webapp
Enable-SPFeature $feat -Url http://webapp
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/06-toggle-feature.png&quot; alt=&quot;Toggle Feature&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finally, I double checked and verified the timer jobs were now present!&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/07-timerjobspresent.png&quot; alt=&quot;Timer Jobs Present&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I then went to the My Site host URL and got into the queue for provisioning. Within 5 minutes, my personal my site was provisioned!&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-08-02-sharepoint-2013-my-site-timer-jobs-missing/08-mysite-provisioned.png&quot; alt=&quot;My Site Provisioned&quot; /&gt;&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="systems administration" /><category term="software development" /><category term="SharePoint" /><category term="2013" /><category term="powershell" /><category term="mysites" /><category term="social" /><category term="timer job" /><summary type="html">The way My Sites are created in SharePoint 2013 is vastly different from SharePoint 2010, but for good reason. I won’t go into the details of how it’s changed, as Wictor Wilen has done an excellent job of this already in his blog post SharePoint 2013: Personal Site Instantiation Queues and Bad Throughput. I encountered problems with a new development workstation not setting up My Sites for users appropriately - blocking us from testing our solution, which was dependent upon a user having a My Site. In looking online (and in Wictor’s blog post), everything was pointing to checking the following three timer jobs:</summary></entry><entry><title type="html">Getting the confusing SharePoint 2013 SocialDataStoreException</title><link href="https://www.chrisweldon.net/software%20development/2013-05-06-getting-the-confusing-sharepoint-2013-socialdatastoreexception/" rel="alternate" type="text/html" title="Getting the confusing SharePoint 2013 SocialDataStoreException" /><published>2013-05-06T11:34:00+00:00</published><updated>2013-05-06T11:34:00+00:00</updated><id>https://www.chrisweldon.net/software%20development/getting-the-confusing-sharepoint-2013-socialdatastoreexception</id><content type="html" xml:base="https://www.chrisweldon.net/software%20development/2013-05-06-getting-the-confusing-sharepoint-2013-socialdatastoreexception/">&lt;p&gt;As I was writing an app using the new SharePoint 2013 app model the other day, I ran into an issue when I was trying to follow a site automatically through JavaScript:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;The target of the operation was not found. Internal type name: Microsoft.Office.Server.UserProfiles.SocialDataStoreException. Internal error code: 0.&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;!--more--&gt;
&lt;p&gt;The problem seemed fairly straight-forward. The targeted site I wanted to follow couldn’t be found. However, it didn’t make sense. The instance URL I was targeting (https://chrisweldon.sharepoint.com) did in fact exist. Furthermore, I was not already following that site. So, why was this failing?&lt;/p&gt;

&lt;p&gt;Let’s take a look at some code:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SOD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;executeOrDelayUntilScriptLoaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;userProfilesLoaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;SP.UserProfiles.js&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;userProfilesLoaded&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SOD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;executeFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;userprofile&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;SP.Social.SocialFollowingManager&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;followSites&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;followSites&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ClientContext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get_current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;socialManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Social&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SocialFollowingManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;socialSite&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Social&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SocialActorInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;socialSite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;set_contentUri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;https://chrisweldon.sharepoint.com&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;socialSite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;set_actorType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SP&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Social&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;SocialActorType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;site&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;socialManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;follow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;socialSite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;executeQueryAsync&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Sites followed!&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; 
        &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;alert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;Error: &lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;get_message&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This is fairly straight-forward. I simply setup a social actor to follow and call out to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SocialFollowingManager&lt;/code&gt; to attempt to follow that site. This is when I thought, perhaps this is a permissions problem? I’m trying to have the JavaScript object model &lt;em&gt;write&lt;/em&gt; a request to the Social datastore. Perhaps it wasn’t authorized.&lt;/p&gt;

&lt;p&gt;I changed the permissions in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AppManifest.xml&lt;/code&gt; from &lt;strong&gt;Read&lt;/strong&gt; to &lt;strong&gt;Write&lt;/strong&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Scope&lt;/th&gt;
      &lt;th&gt;Permission&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;User Profiles (Social)&lt;/td&gt;
      &lt;td&gt;Write&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Sadly, I received the same error message. However, if you read the &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/jj163864.aspx&quot;&gt;MSDN Documentation on Developing Social Features in SharePoint 2013&lt;/a&gt;, there is a section in there talking about user profiles:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;User Profiles (http://sharepoint/social/tenant) The permission request scope used to access all user profiles. Only the profile picture can be changed; all other user profile properties are read-only for apps for SharePoint. Apps that request rights for the User Profiles scope must be installed by a tenant administrator.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a nutshell, I have to grant &lt;strong&gt;Tenant&lt;/strong&gt; permissions to my app to be able to have my user follow a new site. Therefore, my new permissions look like the following:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Scope&lt;/th&gt;
      &lt;th&gt;Permission&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;User Profiles (Social)&lt;/td&gt;
      &lt;td&gt;Read&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;Tenant&lt;/td&gt;
      &lt;td&gt;Write&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;As indicated by the paragraph above, the app now needs to be installed by a tenant administrator. However, in doing so, the app now follows sites (and other content) with ease. Why the obscure error message? That I don’t know, and I hope the SharePoint team might look to address this with a more &lt;em&gt;correct&lt;/em&gt; error message in the near future.&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="Software Development" /><category term="sharepoint" /><category term="2013" /><category term="sp2013" /><category term="social" /><category term="socialdatastoreexception" /><category term="javascript" /><category term="client object model" /><category term="tenant" /><summary type="html">As I was writing an app using the new SharePoint 2013 app model the other day, I ran into an issue when I was trying to follow a site automatically through JavaScript:</summary></entry><entry><title type="html">MigrateUsersToClaims - Operation is not valid due to the current state of the object</title><link href="https://www.chrisweldon.net/systems%20administration/2013-04-30-migrateuserstoclaims-operation-is-not-valid-due-to-the-current-state-of-the-object/" rel="alternate" type="text/html" title="MigrateUsersToClaims - Operation is not valid due to the current state of the object" /><published>2013-04-30T11:50:00+00:00</published><updated>2013-04-30T11:50:00+00:00</updated><id>https://www.chrisweldon.net/systems%20administration/migrateuserstoclaims-operation-is-not-valid-due-to-the-current-state-of-the-object</id><content type="html" xml:base="https://www.chrisweldon.net/systems%20administration/2013-04-30-migrateuserstoclaims-operation-is-not-valid-due-to-the-current-state-of-the-object/">&lt;p&gt;I’m in the process of migrating my customer from SharePoint 2010 to SharePoint 2013. In their SharePoint 2010 environment, they were still using classic-mode authentication, but are switching to claims-based authentication in SharePoint 2013.&lt;/p&gt;

&lt;p&gt;The recommended path to upgrade from 2010 to 2013 is a content and service-application database migration. This works great for us since we &lt;strong&gt;have&lt;/strong&gt; to do this piecemeal. However, many of the general approaches for converting to claims-based authentication is to do so at the web-application level, rather than the content-database level (source: &lt;a href=&quot;http://technet.microsoft.com/en-us/library/gg251985.aspx&quot;&gt;TechNet&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In SharePoint 2013, there’s actually an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SPWebApplication&lt;/code&gt; method dubbed &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/jj172686.aspx&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MigrateUsersToClaims&lt;/code&gt;&lt;/a&gt; that takes 3 arguments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;NTAccount&lt;/li&gt;
  &lt;li&gt;removePermissionsAfter&lt;/li&gt;
  &lt;li&gt;SPWebApplication.SPMigrateUserParameters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There was no guidance on the NTAccount, other than the user “performing” the operation. I opted to use the farm account to ensure it had the appropriate level of permissions. The true power of the content database migration comes in with the third parameter. We can add individual content databases to migrate with this parameter rather than worrying about the &lt;em&gt;entire&lt;/em&gt; web application.&lt;/p&gt;

&lt;p&gt;Props go to &lt;a href=&quot;http://blogs.technet.com/b/speschka/archive/2012/07/23/converting-a-classic-auth-content-database-to-claims-auth-in-sharepoint-2013.aspx&quot;&gt;Steve Peschka&lt;/a&gt; who originally pointed this out. However, in his post, the PowerShell to do this upgrade was the following:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;-- SNIP -- 
$wa.MigrateUsersToClaims($acc, $true, $arguments)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;For me, that throws the error &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Exception calling &quot;MigrateUsersToClaims&quot; with &quot;3&quot; argument(s): &quot;Operation is not valid due to the current state of the object.&quot;&lt;/code&gt; This was strange, and I couldn’t figure it out. So, I cracked open the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Microsoft.SharePoint.Administration&lt;/code&gt; dll and took a look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MigrateUsersToClaims&lt;/code&gt; method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-csharp&quot; data-lang=&quot;csharp&quot;&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;MigrateUsersToClaims&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NTAccount&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;removePermissionsAfter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SPWebApplication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SPMigrateUserParameters&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NTAccount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;account&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ArgumentNullException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;account&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;removePermissionsAfter&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HasDatabaseToMigrate&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parameters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OnlyMigratePolicyUsers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;InvalidOperationException&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// The rest&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;That second one was the one that I questioned. I know the conditions matched for the first two checks. The question was how my parameters looked. Sure enough:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;PS &amp;gt; $arguments

DatabasesToMigrate      HasDatabaseToMigrate        OnlyMigratePolicyUsers
------------------      --------------------        ----------------------
{WSS_MigrationTest_...}                 True                         False&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;With that, if I changed the middle parameter from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$true&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$false&lt;/code&gt;, the migration finally ran (and completed) succesfully.&lt;/p&gt;

&lt;p&gt;Why did this happen? This was because my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$acc&lt;/code&gt; user is my &lt;strong&gt;farm account&lt;/strong&gt;. I’m also running my PowerShell session as my &lt;strong&gt;farm account&lt;/strong&gt;. This is to ensure that I have full, unfettered access to the SharePoint Object Model and the Content Database. The middle parameter states (from &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/jj172686.aspx&quot;&gt;MSDN&lt;/a&gt;):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The &lt;strong&gt;account&lt;/strong&gt; will be given the correct permissions to perform the operation. Should this permission be removed when the operation is complete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We definitely don’t want this for the farm account. So, my updated code, for reference:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot; data-lang=&quot;text&quot;&gt;$wa = Get-SPWebApplication http://my-app-url
$acc = &quot;domain\farm-account&quot;
$arguments = New-Object Microsoft.SharePoint.Administration.SPWebApplication+SPMigrateUserParameters

$contentDb = $wa.ContentDatabase[&quot;Content Database Name&quot;]
$arguments.AddDatabaseToMigrate($contentDb)
$wa.MigrateUsersToClaims($acc, $false, $arguments)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Cheers. Once again, thanks go to &lt;a href=&quot;http://blogs.technet.com/b/speschka/archive/2012/07/23/converting-a-classic-auth-content-database-to-claims-auth-in-sharepoint-2013.aspx&quot;&gt;Steve Peschka&lt;/a&gt; for figuring this out.&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="Systems Administration" /><category term="sharepoint" /><category term="claims" /><category term="identity" /><category term="migration" /><summary type="html">I’m in the process of migrating my customer from SharePoint 2010 to SharePoint 2013. In their SharePoint 2010 environment, they were still using classic-mode authentication, but are switching to claims-based authentication in SharePoint 2013.</summary></entry><entry><title type="html">Sorry, only tenant administrators can add or give access to this app</title><link href="https://www.chrisweldon.net/software%20development/systems%20administration/2013-04-30-sorry-only-tenant-administrators-can-add-this-app/" rel="alternate" type="text/html" title="Sorry, only tenant administrators can add or give access to this app" /><published>2013-04-30T10:41:00+00:00</published><updated>2013-04-30T10:41:00+00:00</updated><id>https://www.chrisweldon.net/software%20development/systems%20administration/sorry-only-tenant-administrators-can-add-this-app</id><content type="html" xml:base="https://www.chrisweldon.net/software%20development/systems%20administration/2013-04-30-sorry-only-tenant-administrators-can-add-this-app/">&lt;p&gt;I have just completed building my first SharePoint 2013 application. I came across the error message &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Sorry, only tenant administrators can add or give access to this app.&lt;/code&gt; when trying to deploy the application to my site. This happened regardless if I was deploying using a SharePoint development site or after installing the solution in the app catalog.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:center&quot; src=&quot;/images/posts/2013-04-30-sorry-only-tenant-administrators-can-add-this-app/error.png&quot; alt=&quot;Error Message&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The application required Tenant Read permissions as I’m accessing the User Profile through the JavaScript object model. The purpose of using the User Profile JSOM is to get the suggestions of sites and people to follow that SharePoint presents.&lt;/p&gt;

&lt;p&gt;Now, the concept of a “Tenant” makes sense for Office 365 or SharePoint Online. As a hosting provider, there are multiple tenants you want to support in a single environment. However, for an on-premise deployment, this error message didn’t make much sense. I started poking around and came across &lt;a href=&quot;http://www.social-point.com/tenant-administration-sites&quot;&gt;spinning up a tenant administration site&lt;/a&gt;, being able to set multiple app tenants through the &lt;a href=&quot;http://technet.microsoft.com/en-us/library/jj219772.aspx&quot;&gt;App Management Service cmdlets&lt;/a&gt;, but none of those really seemed like the right solution for my on-premise deployment. I found an &lt;a href=&quot;http://social.msdn.microsoft.com/Forums/en-US/sharepointdevelopment/thread/4e844f6c-2b73-46ff-9cda-05105332b8f8&quot;&gt;MDSN Forum Question&lt;/a&gt; which seemed closer to the solution. That post recommends splitting the service accounts used to host the App Management and Site Settings services from the farm account. This was critical as the Farm Account is &lt;strong&gt;not allowed&lt;/strong&gt; to add apps under its identity whatsoever. You will get an error message when trying to provision, and the ULS logs will indicate that an assertion failed checking that the current account was not the system account.&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;float:right&quot; src=&quot;/images/posts/2013-04-30-sorry-only-tenant-administrators-can-add-this-app/success.png Provision&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;What did it turn out to be? I just needed to make sure my user account was &lt;strong&gt;directly&lt;/strong&gt; added as a member of the &lt;strong&gt;Farm Administrators&lt;/strong&gt; group. We have traditionally deployed farm administrators via an Active Directory and local (Administrators) group. However, it appears that the App Management service dislikes this approach and wants users &lt;em&gt;explicitly&lt;/em&gt; permissioned to the &lt;strong&gt;Farm Administrators&lt;/strong&gt; group. Additionally, after granting your user direct permissions, you need to issue an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;iisreset&lt;/code&gt; so those changes take effect. Then, you can provision your app successfully.&lt;/p&gt;</content><author><name>Chris Weldon</name><email>chris@chrisweldon.net</email></author><category term="Software Development" /><category term="Systems Administration" /><summary type="html">I have just completed building my first SharePoint 2013 application. I came across the error message Sorry, only tenant administrators can add or give access to this app. when trying to deploy the application to my site. This happened regardless if I was deploying using a SharePoint development site or after installing the solution in the app catalog.</summary></entry></feed>