Hot questions for Using Azure in spring

Question:

I cannot get my Spring Boot site to respond on an Azure Web Instance. I've followed the Java app instructions and the upload instructions. It appears that the IIS server is receiving the request, but the servlet in the war is not responding. According to the documentation, there are a couple of gotchas. In particular, the web.config should be deployed to wwwroot and specify the java path as well as the forwarding port. I believe I've covered these bases -- my web.config is pasted below.

I did try deploying a tomcat server from the marketplace, and that worked fine. When I substitute my war file and web.config, the spring boot app does not work.

One interesting piece of information is that the HTTP_PLATFORM_PORT environment variable does not appear to be defined.

App Settings:

Azure Console Info (Env variables and Web.config):

D:\home\site\wwwroot

> dir
D:\home\site\wwwroot
Volume in drive D is Windows
 Volume Serial Number is 789E-197B

 Directory of D:\home\site\wwwroot

03/01/2016  02:14 AM    <DIR>          .
03/01/2016  02:14 AM    <DIR>          ..
02/29/2016  08:15 PM    <DIR>          bin
03/01/2016  01:49 AM         8,771,899 web-0.0.1-SNAPSHOT.war
03/01/2016  02:10 AM               496 web.config
03/01/2016  02:08 AM               496 web.custom.config
03/01/2016  01:54 AM             4,868 web.tomcat.config
03/01/2016  02:14 AM    <DIR>          webapps



> echo %java_home%
D:\home\site\wwwroot
D:\Program Files\Java\jdk1.8.0_60


> echo %http_platform_port%
D:\home\site\wwwroot
%http_platform_port%


> cat web.config
D:\home\site\wwwroot
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
    </handlers>
    <httpPlatform processPath="%JAVA_HOME%\bin\java.exe"
        arguments="-Djava.net.preferIPv4Stack=true -Dserver.port=%HTTP_PLATFORM_PORT% -jar &quot;%HOME%\site\wwwroot\web-0.0.1-SNAPSHOT.war&quot;">
    </httpPlatform>
  </system.webServer>
</configuration>

Answer:

Shouldn't that be an executable JAR instead of a WAR? You can run a Spring Boot JAR with just JDK 8 installed, but you need a Java EE app server to deploy a WAR to.

I don't know what the web.config file is; I use Cloud Foundry. All I need is a JAR, a .yml file for configuration, and a JDK. The Spring Boot JAR should have the entire application and its dependencies inside. I use Maven to create the fat JAR.

Question:

It's been quite a while since I'm banging my head against this: multipart/mixed content.

  @RequestPart(name="view") CoolView,
  @RequestPart(name="files") Part [] files

Also using spring's (it does not matter because CommonsMultipartResolver fails too) :

  StandardServletMultipartResolver

Now the thing is that when uploading files that have some names outside US_ASCII characters, the server is converting them into something weird. And by weird I mean it converts them to ISO_8859_1, and I think I've set the UTF-8 encoding everywhere imaginable.

  • -Dfile.encoding=UTF-8
  • LANG="en_US.UTF-8" LC_ALL="en_US.UTF-8"
  • URIEncoding = UTF-8 (in server.xml tomcat)
  • CharacterEncodingFilter is the first filter that is being picked up
  • It's interesting that this only happens when I try this on the azure linux machine, locally everything is just fine.

    For example I'm using curl to send some files to be uploaded :

      curl -X POST -F "files=@Définition fonctionnalités.pdf" 
    

    And in Controller I'm trying to see the name that is actually being captured from Content-Disposition filename.

      Définition fonctionnalités.pdf 
    

    At this point I would accept any suggestion what-so-ever. thank u


    Answer:

    According to your description, the string Définition fonctionnalités.pdf can be converted into the correct string by the below code.

    String str = new String("Définition fonctionnalités.pdf".getBytes("ISO-8859-1"), "UTF-8");
    System.out.println(str); // Output is "Définition fonctionnalités.pdf"
    

    Per my experience, it seems to be caused by the Character Encoding format of your Java source file if your development environment is on Windows.

    So for the case, the solution is using the text editor supported UTF-8 Encoding to be sure the encoding format of Java source files before compiling them.

    If you are using Eclipse IDE, you can set the encoding for your project. The steps as below.

    1. Select your project to right click to select the Properties or directly enter the combine keys Alt+Enter.
    2. Set up the text file encoding for the current project in the Resource tab, please see below.

    Note: If you set the text file encoding for the existing project, you may need to repair these incorrect encoding string manually。

    Hope it helps.


    Update: Please try to do some configurations below.

    1. Configuring the server.xml file for connection to enable the URIEncoding with UTF-8.

      <Connector port="80" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" URIEncoding="UTF-8"/> 
      
    2. Adding a global filter for your Java webapp.

    Configure the web.xml file for your project

    <filter>
        <filter-name>charsetFilter</filter-name>
        <filter-class>com.XXXX.xxxx.CharsetFilter</filter-class>
        <init-param>
            <param-name>requestEncoding</param-name>
           <param-value>UTF-8</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>charsetFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

    Create the filter class CharsetFilter

    public class CharsetFilter implements Filter {
        private String encoding;
        private Logger log = Logger.getLogger(this.getClass());
    
        public void init(FilterConfig config) throws ServletException {
            encoding = config.getInitParameter("requestEncoding");
            if (encoding == null) encoding = "UTF-8";
        }
    
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain next)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            request.setCharacterEncoding(encoding);
            next.doFilter(request, response);
        }
    
        public void destroy() {
        }
    }
    
    1. When receiving the uploaded file, converting the bytes of the file name string with ISO-8859-1 into a UTF-8 string, as I said above.

      String originFN = ....;
      String fileName = new String(originFN.getBytes("ISO-8859-1"), "UTF-8");
      

    Question:

    I tried to create a project in springboot with azure and after I generated my pom. I got an error:

    Project build error: Non-resolvable parent POM for org.springframework.boot:spring-boot-starter-parent:[unknown-version]: Failure to transfer org.springframework.boot:spring-boot-dependencies:pom:2.1.0.RELEASE from https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced. Original error: Could not transfer artifact org.springframework.boot:spring-boot-dependencies:pom:2.1.0.RELEASE from/to central (https://repo.maven.apache.org/maven2): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    Here's my pom.xml

     <?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
        http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>ph.com.meralco.imcs</groupId>
        <artifactId>IMCS_Azure_Test</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
    
        <name>IMCS_Azure_Test</name>
        <description>Demo Web App for IMCS Azure Integration</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.0.RELEASE</version>
            <relativePath/>  <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF- 
        8</project.reporting.outputEncoding>
            <azure.version>2.0.5</azure.version>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-active-directory-spring-boot-starter</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-jose</artifactId>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.microsoft.azure</groupId>
                    <artifactId>azure-spring-boot-bom</artifactId>
                    <version>${azure.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
    
        </dependencyManagement>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build> 
        </project>
    

    Answer:

    From the logs, this seems to be a network issue as your local intranet is not allowing your IDE to download dependencies from public maven repository. Try changing your network and start downloading dependencies.

    Question:

    I'm going through a tutorial on Microsoft Docs on how to secure my Spring MVC application using Spring Boot Starter for Azure Active Directory. I'm trying to secure the admin area of my site. I have a @PreAuthorize annotation on a controller method that I only want users in the admin group to have access to. I am able to get a login prompt, but after succesfully logging in I get a 403 for that controller method. When I remove the @PreAuthorize annotation, I can log in and access the method just fine.

    Here is the controller method:

    @Controller
    public class PostController {
    
        ...
    
        @PreAuthorize("hasRole('admin')")
        @RequestMapping(path = "/admin/post", method = RequestMethod.GET)
        public String getPost(@ModelAttribute("post") Post post, Model model) {
            List<Tag> tags = tagService.getAll();
            model.addAttribute("tags", tags);
            return "post";
        }
    
        ...
    

    Here is the WebSecurityConfig.java:

    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .authorizeRequests()
                .antMatchers("/admin/**").authenticated()
                .and()
                .oauth2Login()
                .userInfoEndpoint()
                .oidcUserService(oidcUserService);
        }
    }
    

    Here is the application.properties:

    # Azure AD
    # Specifies your Active Directory ID:
    azure.activedirectory.tenant-id=<my-ad-tenant-id>
    
    # Specifies your App Registration's Application ID:
    spring.security.oauth2.client.registration.azure.client-id=<my-app-registration-app-id>
    
    # Specifies your App Registration's secret key:
    spring.security.oauth2.client.registration.azure.client-secret=<my-client-secret>
    
    # Specifies the list of Active Directory groups to use for authorization:
    azure.activedirectory.activeDirectoryGroups=admin
    

    Here is the app registration manifest:

    {
        "id": "<id>",
        "acceptMappedClaims": null,
        "accessTokenAcceptedVersion": null,
        "addIns": [],
        "allowPublicClient": null,
        "appId": "<app-id>",
        "appRoles": [],
        "oauth2AllowUrlPathMatching": false,
        "createdDateTime": "2020-04-10T23:37:26Z",
        "groupMembershipClaims": null,
        "identifierUris": [],
        "informationalUrls": {
            "termsOfService": null,
            "support": null,
            "privacy": null,
            "marketing": null
        },
        "keyCredentials": [],
        "knownClientApplications": [],
        "logoUrl": null,
        "logoutUrl": null,
        "name": "test",
        "oauth2AllowIdTokenImplicitFlow": true,
        "oauth2AllowImplicitFlow": true,
        "oauth2Permissions": [],
        "oauth2RequirePostResponse": false,
        "optionalClaims": null,
        "orgRestrictions": [],
        "parentalControlSettings": {
            "countriesBlockedForMinors": [],
            "legalAgeGroupRule": "Allow"
        },
        "passwordCredentials": [
            {
                "customKeyIdentifier": null,
                "endDate": "2299-12-31T05:00:00Z",
                "keyId": "<key-id>",
                "startDate": "2020-04-10T23:39:47.917Z",
                "value": null,
                "createdOn": "2020-04-10T23:39:48.4572747Z",
                "hint": "SVb",
                "displayName": "test key"
            }
        ],
        "preAuthorizedApplications": [],
        "publisherDomain": "test.onmicrosoft.com",
        "replyUrlsWithType": [
            {
                "url": "http://localhost:8080/login/oauth2/code/azure",
                "type": "Web"
            }
        ],
        "requiredResourceAccess": [
            {
                "resourceAppId": "<resource-app-id>",
                "resourceAccess": [
                    {
                        "id": "<resource-access-id>",
                        "type": "Scope"
                    }
                ]
            }
        ],
        "samlMetadataUrl": null,
        "signInUrl": null,
        "signInAudience": "AzureADMyOrg",
        "tags": [],
        "tokenEncryptionKeyId": null
    }
    

    Here's the group in Azure:

    The user I'm signing in with is a member of this group. According to the documentation, only users that are not authorized should receive a 403. I've tried changing the hasRole() parameter to 'ROLE_admin' but that does not work. I've also tried to configure the hasRole("admin") in the WebSecurityConfig.java like this:

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/admin/**").authenticated()
            .antMatchers("/admin/**").hasRole("admin")
            .and()
            .oauth2Login()
            .userInfoEndpoint()
            .oidcUserService(oidcUserService);
    }
    

    But that does not work either. I've been at this for a couple of days but I cannot figure out why I'm getting a 403 when the user I'm signing in with is in the admin group.

    EDIT

    pom.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.5.RELEASE</version>
        </parent>
        <groupId>me.test</groupId>
        <artifactId>test-me</artifactId>
        <version>1.0</version>
        <packaging>war</packaging>
        <name>test.me</name>
    
        <properties>
            <java.version>1.8</java.version>
            <azure.version>2.2.0</azure.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-active-directory-spring-boot-starter</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-thymeleaf</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.security</groupId>
                <artifactId>spring-security-oauth2-jose</artifactId>
            </dependency>
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity5</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>com.microsoft.sqlserver</groupId>
                <artifactId>mssql-jdbc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>6.1.0.Final</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-configuration-processor</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.9</version>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-storage-blob</artifactId>
                <version>12.5.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.microsoft.azure</groupId>
                    <artifactId>azure-spring-boot-bom</artifactId>
                    <version>${azure.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
    
        <build>
        <finalName>ROOT</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
                <plugin>
                    <artifactId>maven-failsafe-plugin</artifactId>
                    <executions>
                        <execution>
                            <goals>
                                <goal>integration-test</goal>
                                <goal>verify</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    You can view the Microsoft Spring Boot / Azure AD sample in GitHub.


    Answer:

    According to my research, if we want to retrieves user's group membership using graph API which requires the registered app to have Direcory.AccessAsUser.All permissions. For more details, please refer to the document and the document.

    For example

    1. Update permissions

    2. application.properties

    # Azure AD
    # Specifies your Active Directory ID:
    azure.activedirectory.tenant-id=<my-ad-tenant-id>
    
    # Specifies your App Registration's Application ID:
    spring.security.oauth2.client.registration.azure.client-id=<my-app-registration-app-id>
    
    # Specifies your App Registration's secret key:
    spring.security.oauth2.client.registration.azure.client-secret=<my-client-secret>
    
    # Specifies the list of Active Directory groups to use for authorization:
    azure.activedirectory.activeDirectoryGroups=SQLAdmin
    
    # Configure log level
    logging.level.root=Debug
    
    1. WebSecurityConfig.java
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .authorizeRequests()
                    .antMatchers("/admin/**").authenticated()
                    .and()
                    .oauth2Login()
                    .userInfoEndpoint()
                    .oidcUserService(oidcUserService);
        }
    }
    
    1. Controller
     @Autowired
        @PreAuthorize("hasRole('SQLAdmin')")
        @GetMapping("/admin")
        @ResponseBody
        public String helloWorld() {
            return "Hello World!";
        }
    

    Question:

    My Code breaks when it reaches to this line.

    String resp = restTemplate.postForObject(URL, json, String.class);
    

    On my localhost its working fine but on dev-env server, The error is:

    Error occured in java.lang.NoSuchMethodError: com.microsoft.applicationinsights.agent.internal.coresync.impl.ImplementationsCoordinator.httpMethodFinished(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IJ)V

    The dev-env is Azure Application Service including Java 8 and Tomcat 9.


    Answer:

    It seems to be like a library issue: somehow your environment has two incompatible versions of the same library. Just run

    mvn dependency:tree
    

    or remove manually the invalid jar.

    Question:

    Im trying to build and deploy a Spring API on Azure via a Yaml pipeline. But i get an error during the spring application gradle build saying.

    Error: /home/vsts/work/1/s/gradlew failed with return code: 1

    Could not find org.springframework.boot:spring-data-rest-hal-browser:

    Expanding the Error,

    Starting a Gradle Daemon (subsequent builds will be faster)
    > Task :compileJava FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Could not resolve all files for configuration ':compileClasspath'.
    > Could not find org.springframework.boot:spring-data-rest-hal-browser:.
      Required by:
          project :
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Get more help at https://help.gradle.org
    
    BUILD FAILED in 39s
    1 actionable task: 1 executed
    Error: /home/vsts/work/1/s/gradlew failed with return code: 1
        at ChildProcess.<anonymous> (/home/vsts/work/_tasks/Gradle_8d8eebd8-2b94-4c97-85af-839254cc6da4/2.151.0/node_modules/vsts-task-lib/toolrunner.js:639:25)
        at emitTwo (events.js:106:13)
        at ChildProcess.emit (events.js:191:7)
        at maybeClose (internal/child_process.js:886:16)
        at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
    ##[error]Error: /home/vsts/work/1/s/gradlew failed with return code: 1
    ##[section]Finishing: Gradle
    

    Things i have tried.

    I have tried changing specifying the versions of spring-data-rest-hal-browser in my project from. compile("org.springframework.boot:spring-data-rest-hal-browser") to compile("org.springframework.boot:spring-data-rest-hal-browser:2.4.0.RELEASE") and finally compile("org.springframework.boot:spring-data-rest-hal-browser:3.0.8.RELEASE")

    But still the same Error results

    This is my current build.gradle file in my repo

    plugins {
        id 'org.springframework.boot' version '2.1.3.RELEASE'
        id 'java'
    }
    
    apply plugin: 'io.spring.dependency-management'
    
    group = 'com.test.spring.api'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.11'
    
    repositories {
        mavenCentral()
    }
    
    configurations {
        developmentOnly
        runtimeClasspath {
            extendsFrom developmentOnly
        }
    }
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-data-rest'
        runtimeOnly 'mysql:mysql-connector-java'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        developmentOnly("org.springframework.boot:spring-boot-devtools")
    
        compile("org.springframework.boot:spring-boot-starter-data-rest")
        compile("org.springframework.boot:spring-boot-starter-data-jpa")
        compile("org.springframework.boot:spring-data-rest-hal-browser")
        compile("org.springframework.data:spring-data-rest-webmvc:3.1.5.RELEASE")
    }
    

    And this is my current azure-pipelines.yml file

    # Maven
    # Build your Java project and run tests with Apache Maven.
    # Add steps that analyze code, save build artifacts, deploy, and more:
    # https://docs.microsoft.com/azure/devops/pipelines/languages/java
    
    trigger:
    - master
    
    pool:
      vmImage: 'Ubuntu-16.04'
    
    steps:
    - task: Gradle@2
      inputs:
        workingDirectory: '$(system.defaultWorkingDirectory)'
        gradleWrapperFile: 'gradlew'
        gradleOptions: '-Xmx3072m'
        javaHomeOption: 'JDKVersion'
        jdkVersionOption: '1.8'
        jdkArchitectureOption: 'x64'
        publishJUnitResults: false
        testResultsFiles: '**/TEST-*.xml'
        tasks: 'build'
    
    - task: CopyFiles@2
      displayName: 'Copy Files to: Wireframe Directory on development server'
      inputs:
        SourceFolder: '$(Build.SourcesDirectory)'
    
        TargetFolder: '$(Build.ArtifactStagingDirectory)'
    
    - script: 
          cd '$(Build.ArtifactStagingDirectory)';
          ls
    
    - task: FtpUpload@1
      displayName: 'FTP Upload: $(Build.ArtifactStagingDirectory)'
      inputs:
        credentialsOption: inputs
    
        serverUrl: '[test server url]'
    
        username: '[test username] '
    
        password: '[test password] '
    
        rootDirectory: '$(Build.ArtifactStagingDirectory)'
    
        remoteDirectory: D:\home\site\wwwroot\webapps\ROOT\
    
        preservePaths: true
    

    I want to be able to automatically deploy my spring application to the server URL by pushing my code to it via the Azure devops pipeline which would build and deploy the spring application.

    Thanks


    Answer:

    So i resolved the issue by making some changes to the build.gradle file and build pipeline using help from the Microsoft Azure Repository for Intellij on Github: see here

    My new build.gradle file looks like this:

    plugins {
        id 'org.jetbrains.intellij' version '0.4.1' apply false
        id 'org.springframework.boot' version '2.1.3.RELEASE'
        id 'java'
    }
    
    /**
     *This is task for update Gradle wrapper version.
     */
    task wrapper(type: Wrapper) {
        gradleVersion = '4.7'
        distributionUrl = "https://services.gradle.org/distributions/gradle-${gradleVersion}-all.zip"
    }
    
    apply plugin: 'io.spring.dependency-management'
    
    group = 'com.test.spring.api'
    version = '0.0.1-SNAPSHOT'
    sourceCompatibility = '1.8'
    
    repositories {
        mavenCentral()
    }
    
    allprojects {
    
    configurations {
        developmentOnly
        runtimeClasspath {
            extendsFrom developmentOnly
        }
    }
    
        repositories {
            mavenCentral()
        }
    }
    
    task unitTest(type: Test) {
        exclude '**/ApplicationTests/**'
    }
    
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter-data-rest'
        runtimeOnly 'mysql:mysql-connector-java'
        testImplementation 'org.springframework.boot:spring-boot-starter-test'
        developmentOnly("org.springframework.boot:spring-boot-devtools")
    
        compile("org.springframework.boot:spring-boot-starter-data-rest")
        compile("org.springframework.boot:spring-boot-starter-data-jpa")
        compile group: 'org.springframework.data', name: 'spring-data-rest-hal-browser', version: '3.0.8.RELEASE'
        compile("org.springframework.data:spring-data-rest-webmvc:3.1.5.RELEASE")
    }
    
        tasks.withType(JavaCompile) {
            options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
        }
    
        tasks.withType(FindBugs) {
            ignoreFailures = true
            reports {
                html { enabled = true }
                xml.enabled = !html.enabled
            }
        }
    
        /**
         * Preparing for release build
         */
        task prepRelease() {
        }
    

    Also modified the azure-pipelines.yml file to include stacktrace and info to assist in debugging other gradle and build errors.

     tasks: 'build --stacktrace --info'
    

    Question:

    I'm trying to deploy simple Spring Boot app to Azure App Service, but looks like app doesn't starts.

    My app has on rest endpoint

    @RequestMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }
    

    I tried to deploy using azure-webapp-maven-plugin, config in pom looks like this

      <plugin>
                <groupId>com.microsoft.azure</groupId>
                <artifactId>azure-webapp-maven-plugin</artifactId>
                <version>1.7.0</version>
                <configuration>
                    <schemaVersion>V2</schemaVersion>
    
                    <!-- Web App information -->
                    <resourceGroup>${resourceGroup}</resourceGroup>
                    <appName>boot-test-app</appName>
                    <region>westeurope</region>
                    <pricingTier>P1V2</pricingTier>
                    <runtime>
                        <os>linux</os>
                        <javaVersion>jre8</javaVersion>
                        <webContainer>tomcat 8.5</webContainer>
                    </runtime>
                    <appSettings>
                        <property>
                             <name>PORT</name>
                            <value>80</value>
                        </property>
                        <property>
                            <name>JAVA_OPTS</name>
                            <value>-Xmx512m -Xms512m</value>
                        </property>
                    </appSettings>
                    <deployment>
                        <resources>
                            <resource>
                                <directory>${project.basedir}/target</directory>
                                <!--<targetPath>/home/site/wwwroot/webapps/ROOT/</targetPath>-->
                                <includes>
                                    <include>*.war</include>
                                </includes>
                            </resource>
                        </resources>
                    </deployment>
                </configuration>
            </plugin>
    

    Plugin says deploy was successful, but when i'm opening app webpage - i got 404 error. The same if I'm deploying using Azure Plugin for Intellij Idea.

    What i'm missing? Thanks!


    Answer:

    Please follow this tutorial to deploy:Spring Boot on Linux. I test multiple times, this works for. Or you could just use my pom.xml file.

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">  
      <modelVersion>4.0.0</modelVersion>  
      <groupId>org.springframework</groupId>  
      <artifactId>gs-spring-boot</artifactId>  
      <version>0.1.0</version>  
      <parent> 
        <groupId>org.springframework.boot</groupId>  
        <artifactId>spring-boot-starter-parent</artifactId>  
        <version>2.1.6.RELEASE</version> 
      </parent>  
      <dependencies> 
        <dependency> 
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-starter-web</artifactId> 
        </dependency>  
        <!-- tag::actuator[] -->  
        <dependency> 
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-starter-actuator</artifactId> 
        </dependency>  
        <!-- end::actuator[] -->  
        <!-- tag::tests[] -->  
        <dependency> 
          <groupId>org.springframework.boot</groupId>  
          <artifactId>spring-boot-starter-test</artifactId>  
          <scope>test</scope> 
        </dependency>  
        <!-- end::tests[] --> 
      </dependencies>  
      <properties> 
        <java.version>1.8</java.version> 
      </properties>  
      <build> 
        <plugins> 
          <plugin> 
            <groupId>org.springframework.boot</groupId>  
            <artifactId>spring-boot-maven-plugin</artifactId> 
          </plugin>  
          <plugin> 
            <groupId>com.microsoft.azure</groupId>  
            <artifactId>azure-webapp-maven-plugin</artifactId>  
            <version>1.6.0</version>  
            <configuration>
              <schemaVersion>V2</schemaVersion>
              <resourceGroup>group name</resourceGroup>
              <appName>app name</appName>
              <region>westeurope</region>
              <pricingTier>P1V2</pricingTier>
    
    
              <!-- Begin of App Settings  -->
              <appSettings>
                 <property>
                       <name>JAVA_OPTS</name>
                       <value>-Dserver.port=80</value>
                 </property>
              </appSettings>
    
              <runtime>
                <os>linux</os>
                <javaVersion>jre8</javaVersion>
                <webContainer>jre8</webContainer>
              </runtime>
              <deployment>
                <resources>
                  <resource>
                    <directory>${project.basedir}/target</directory>
                    <includes>
                      <include>*.jar</include>
                    </includes>
                  </resource>
                </resources>
              </deployment>
            </configuration>
          </plugin>  
          <plugin> 
            <artifactId>maven-failsafe-plugin</artifactId>  
            <executions> 
              <execution> 
                <goals> 
                  <goal>integration-test</goal>  
                  <goal>verify</goal> 
                </goals> 
              </execution> 
            </executions> 
          </plugin> 
        </plugins> 
      </build> 
    </project>
    

    After deployment, if the web still don't show right page, check the runtime stack if it's same as you defined in the pom.xml.

    Question:

    In my app I'm zipping and then downloading larges files, the files are located in azure, so I read the files from a stream and then zip them one after another, so I can dowload the zip file after all files has been zipped, here's my code:

    @RequestMapping(value = "{analyseId}/download", method = RequestMethod.GET, produces = "application/zip")
    public ResponseEntity<Resource> download(@PathVariable List<String> paths) throws IOException {
    
        String zipFileName = "zipFiles.zip";
        File zipFile = new File(zipFileName);
        FileOutputStream fos = new FileOutputStream(zipFile);
        ZipOutputStream zos = new ZipOutputStream(fos);
        for (String path : paths) {
            InputStream fis = azureDataLakeStoreService.readFile(path);
            addToZipFile(path , zos, fis);
        }
        zos.close();
        fos.close();
        BufferedInputStream zipFileInputStream = new BufferedInputStream(new FileInputStream(zipFile.getAbsolutePath()));
        InputStreamResource resource = new InputStreamResource(zipFileInputStream);
        zipFile.delete();
    
        return ResponseEntity.ok()
                .header(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION)
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + zipFileName)
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(resource);
    }
    
    private static void addToZipFile(String path, ZipOutputStream zos, InputStream fis) throws IOException {
        ZipEntry zipEntry = new ZipEntry(FilenameUtils.getName(path));
        zos.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = fis.read(bytes)) >= 0) {
            zos.write(bytes, 0, length);
        }
        zos.closeEntry();
        fis.close();
    }
    

    However on azure the request time out is set to 230 sec, and cannot be changed, however for big files it takes more than that to load and then zip the files on the server, so the connection with the client will be lost meanwhile.

    So my question is since I'm getting the data from a stream, can we do all these operations simultaneously, means getting the stream and download it as the same time and not waiting till getting the whole file, or if there any other idea can any body share it here please.

    Thanks.


    Answer:

    The answer is to not download the file to the server and then send it to the client but streaming it to the client directly here's the code

    @RequestMapping(value = "/download", method = RequestMethod.GET)
    public StreamingResponseBody download(@PathVariable String path) throws IOException {
    
        final InputStream fecFile = azureDataLakeStoreService.readFile(path);
        return (os) -> {
            readAndWrite(fecFile, os);
        };
    }
    
    private void readAndWrite(final InputStream is, OutputStream os)
            throws IOException {
        byte[] data = new byte[2048];
        int read = 0;
        while ((read = is.read(data)) >= 0) {
            os.write(data, 0, read);
        }
        os.flush();
    }
    

    I also added this configuration to ApplicationInit:

    @Configuration
    public static class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
            configurer.setDefaultTimeout(-1);
            configurer.setTaskExecutor(asyncTaskExecutor());
        }
    
        @Bean
        public AsyncTaskExecutor asyncTaskExecutor() {
            return new SimpleAsyncTaskExecutor("async");
        }
    
    }
    

    Question:

    Azure loads startup details into the System.getenv() properties. I would like them to show up in the Environment variable from Spring.

    How can I accomplish this?

    As a side note, is there a way to add a system variable at startup (for testing?)


    Answer:

    you can add all your properties to application.properties in Spring Boot. otherwise, you can add a Bean in your spring boot application class that reads from the system properties & loads them.

    Question:

    I'm able call 4-5 rest apis, prior to coming to this block of code. But I'm not able to execute this block of code.

    I am using spring 4.0.4 core, mvc jars.

    I am trying to call a azure ucwa web service using rest template, its a post method with string as body. I m getting a 500 internal error. I have searched all over internet and yet did not find solution, Please guide me. Thank you.

    link : https://docs.microsoft.com/en-us/skype-sdk/ucwa/sendanim step 9

    RestTemplate restTemplate = new RestTemplate();
       System.out.println(" jsonLinksObj : 4a "+jsonLinksObj);   
       org.json.JSONObject jsonSendMessageObj = jsonLinksObj.getJSONObject("sendMessage");
       String sendMsgFullUrl = poolUrl.concat(jsonSendMessageObj.getString("href")).concat("?OperationContext=4322131"); 
    
      headers.clear();
      headers.setContentType(MediaType.TEXT_PLAIN);
      headers.set("Authorization", "Bearer " + jwtToken);
    
      String body = "My Send Message Here";
    
                    HttpEntity<Object> entityJsonSendMsg4 = new HttpEntity<Object>(body, headers);
    
    
                     ResponseEntity<Object> sbSendMsgObj  = null;
                   try{
    
                        sbSendMsgObj = restTemplate.exchange(
                            new URI(sendMsgFullUrl), 
                            HttpMethod.POST, 
                            entityJsonSendMsg4, 
                            Object.class);
                   } catch(Exception e){
                            e.printStackTrace();
                   }
    
                                WARN : org.springframework.web.client.RestTemplate - POST request for "https://webpoolpnqin102.infra.lync.com/ucwa/oauth/v1/applications/102086376449/communication/conversations/46db8085-8ad0-4186-a4f0-9a521b256b9b/messaging/messages?OperationContext=4322131" resulted in 500 (Internal Server Error);         invoking error handler
                    org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error
                                    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:94)
                                                                                             at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:589)
                                    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:547)
                                    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:518)
                                    at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:463)
                                    at com.test.example.employee.test.EmployeeTest.sendMessage(EmployeeTest.java:266)
                                      at com.test.example.employee.test.EmployeeTest.main(EmployeeTest.java:337)
                    Exception in thread "main" java.lang.NullPointerException
                                      at com.test.example.employee.test.EmployeeTest.sendMessage(EmployeeTest.java:331)
                                      at com.test.example.employee.test.EmployeeTest.main(EmployeeTest.java:337)
    

    Answer:

    It is hard to say what is the reason behind the 500 you got in response - you probably have to debug it yourself but it should not be very hard.

    Since you created RestTemplate using default constructor you have got a deafault error handling. Run your application in debug mode and place a breakpoint in DefaultResponseErrorHandler::handleError. There you get the access to response represented by ClientHttpResponse class and can actually look into body you got back.

    When you know the reason behind the error you can correct the request accordingly.

    Question:

    EventListener to listen to azure event hub needs to startup on springboot application startup The class in question is

           @Component
            @EnableConfigurationProperties(AzureProperties.class)
            public class EventProcessor {
            private static final Logger LOGGER = LoggerFactory.getLogger(EventProcessor.class);
    
            @Autowired
            private AzureProperties azureProperties;
    
                public void startProcess() throws InterruptedException, ExecutionException {
                    System.out.println("----------------------------------in Post construct---------------------");
                    LOGGER.info(
                            "-------------------------------------Starting in post constriuct----------------------------------");
                    EventProcessorHost host = new EventProcessorHost(
                            EventProcessorHost
                                    .createHostName(azureProperties.getHostNamePrefix()),
                            azureProperties.getEventHubName(),
                            azureProperties.getConsumerGroupName(),
                            azureProperties.getEventHubConnectionString(),
                            azureProperties.getStorageConnectionString(),
                            azureProperties.getStorageContainerName());
                    EventProcessorOptions options = new EventProcessorOptions();
                    host.registerEventProcessor(AzureEventHub.class, options).get();
    
                }
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            try {
                startProcess();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ExecutionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
        }
            }
    

    To start it on spring boot application startup i added the following to the class

    @PostConstruct
    public void init() {
        System.out.println("----------------------------------in INIT construct---------------------");
        try {
            startProcess();
        } catch (InterruptedException e) {
    
            e.printStackTrace();
        } catch (ExecutionException e) {
    
            e.printStackTrace();
        }
    }
    

    However after application startup it doesnt even print or show the logger in console. Isnt @postConstruct supposed to trigger this?

    The main class is

    @EnableDatabaseManagement
    @SpringBootApplication(scanBasePackages={"com.package"})
    @PropertySource(value = "classpath:/secure.properties", ignoreResourceNotFound = true)
    public class Application {
        public static void main(String[] args) throws EventHubException, IOException, InterruptedException, ExecutionException {
            TimeZone.setDefault(TimeZone.getTimeZone("Etc/UCT"));
            DateTimeZone.setDefault(DateTimeZone.forID("Etc/UCT"));
            SpringApplication.run(Application.class, args);
        }
    

    The log i Get here is

      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::       (v1.5.15.RELEASE)
    
    2019-03-07 23:49:44.025  INFO 6456 --- [           main] c.o.c.s.s.sandboxmanager.Application     : Starting Application on 
    2019-03-07 23:49:44.028  INFO 6456 --- [           main] c.o.c.s.s.sandboxmanager.Application     : No active profile set, falling back to default profiles: default
    2019-03-07 23:49:44.093  INFO 6456 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7995092a: startup date [Thu Mar 07 23:49:44 UTC 2019]; root of context hierarchy
    2019-03-07 23:49:44.981  INFO 6456 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'xxxx' with a different definition: replacing [Generic bean: class [com.xxxx.xxxx.clientrouter.xxxxx]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=clientContextExtractionConfiguration; factoryMethodName=xxxx; initMethodName=null; destroyMethodName=(inferred); defined in class path resource 
    2019-03-07 23:49:44.990  INFO 6456 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'jerseyConfigInitBeanPostProcessor' with a different definition: replacing [Generic bean: class [com.xxx.xxxx.jersey.JerseyConfigInitBeanPostProcessor]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in URL [jar:file:/E:/.m2/repository/com/xxxx/cloud/lib/rest-lib/1.7.8/rest-lib-1.7.8.jar!/com/xxxx/cloud/lib/rest/jersey/JerseyConfigInitBeanPostProcessor.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jerseyIntegrationConfiguration; factoryMethodName=jerseyConfigInitBeanPostProcessor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/xxxx/cloud/lib/rest/jersey/JerseyIntegrationConfiguration.class]]
    2019-03-07 23:49:45.497  INFO 6456 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
    2019-03-07 23:49:45.537  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'configurationPropertiesValidator' of type [] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.686  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$13d316d7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.756  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration$$EnhancerBySpringCGLIB$$6f669668] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.764  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration$$EnhancerBySpringCGLIB$$21b35881] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.777  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration$$EnhancerBySpringCGLIB$$dcca3e70] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.795  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties' of type [org.springframework.boot.autoconfigure.jackson.JacksonProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.802  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'standardJacksonObjectMapperBuilderCustomizer' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration$StandardJackson2ObjectMapperBuilderCustomizer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.835  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JodaDateTimeJacksonConfiguration' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JodaDateTimeJacksonConfiguration$$EnhancerBySpringCGLIB$$a6d69ce5] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.839  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jodaDateTimeSerializationModule' of type [com.fasterxml.jackson.databind.module.SimpleModule] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.842  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration' of type [org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$$EnhancerBySpringCGLIB$$517233f7] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.853  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jsonComponentModule' of type [org.springframework.boot.jackson.JsonComponentModule] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.857  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.data.web.config.SpringDataJacksonConfiguration' of type [org.springframework.data.web.config.SpringDataJacksonConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.863  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jacksonGeoModule' of type [org.springframework.data.geo.GeoModule] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.866  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jacksonObjectMapperBuilder' of type [org.springframework.http.converter.json.Jackson2ObjectMapperBuilder] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.891  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jacksonObjectMapper' of type [com.fasterxml.jackson.databind.ObjectMapper] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.906  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jerseyIntegrationConfiguration' of type [com.xxxx.xxxx.jersey.JerseyIntegrationConfiguration$$EnhancerBySpringCGLIB$$a7b38252] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.959  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jacksonJaxbJsonProvider' of type [com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:45.972  INFO 6456 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'jerseyConfig' of type [org.glassfish.jersey.server.ResourceConfig] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    2019-03-07 23:49:46.352  INFO 6456 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8080 (http)
    2019-03-07 23:49:46.380  INFO 6456 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
    2019-03-07 23:49:46.380  INFO 6456 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.15
    2019-03-07 23:49:46.540  INFO 6456 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
    2019-03-07 23:49:46.541  INFO 6456 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 2451 ms
    2019-03-07 23:49:46.837  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'corsFilter' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'activityLoggingFilter' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'xxxx' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
    2019-03-07 23:49:46.838  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
    2019-03-07 23:49:46.839  INFO 6456 --- [ost-startStop-1] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
    2019-03-07 23:49:46.839  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'org.glassfish.jersey.server.ResourceConfig' to [/*]
    2019-03-07 23:49:46.840  INFO 6456 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
    2019-03-07 23:50:05.838  INFO 6456 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
    2019-03-07 23:50:05.857  INFO 6456 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
        name: default
        ...]
    2019-03-07 23:50:05.934  INFO 6456 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.1.0.Final}
    2019-03-07 23:50:05.936  INFO 6456 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
    2019-03-07 23:50:05.938  INFO 6456 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
    2019-03-07 23:50:05.983  INFO 6456 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
    2019-03-07 23:50:06.120  INFO 6456 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.SQLServer2012Dialect
    2019-03-07 23:50:08.214  INFO 6456 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
    2019-03-07 23:50:08.431  INFO 6456 --- [           main] .l.r.j.JerseyConfigInitBeanPostProcessor : Registering com.xxxx.xxxx.monitoring.HealthEndpoint
    2019-03-07 23:50:08.589  INFO 6456 --- [           main] .l.r.j.JerseyConfigInitBeanPostProcessor :
    2019-03-07 23:50:08.622  INFO 6456 --- [           main] .a.p.AzureAdAuthenticationResultProvider : Initializing Azure Active Directory authentication for
    2019-03-07 23:50:08.652  INFO 6456 --- [           main] c.o.c.l.r.c.RestLibCachingConfiguration  : Using default rest-lib EhCache configuration from classpath: ehCache-rest-lib.xml
    2019-03-07 23:50:08.656  INFO 6456 --- [           main] o.s.c.ehcache.EhCacheManagerFactoryBean  : Initializing EhCache CacheManager 'restLibCacheManager'
    2019-03-07 23:50:08.948  INFO 6456 --- [           main] .l.r.j.JerseyConfigInitBeanPostProcessor : Registering xxxx as REST endpoint
    2019-03-07 23:50:09.201  INFO 6456 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@7995092a: startup date [Thu Mar 07 23:49:44 UTC 2019]; root of context hierarchy
    2019-03-07 23:50:09.277  INFO 6456 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
    2019-03-07 23:50:09.278  INFO 6456 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
    2019-03-07 23:50:09.307  INFO 6456 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2019-03-07 23:50:09.307  INFO 6456 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2019-03-07 23:50:09.321  INFO 6456 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in brokenPipeExceptionHandler
    2019-03-07 23:50:09.347  INFO 6456 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**/favicon.ico] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
    2019-03-07 23:50:09.620  INFO 6456 --- [           main] b.a.s.AuthenticationManagerConfiguration : 
    
    
    
    2019-03-07 23:50:09.681  INFO 6456 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/css/**'], Ant [pattern='/js/**'], Ant [pattern='/images/**'], Ant [pattern='/webjars/**'], Ant [pattern='/**/favicon.ico'], Ant [pattern='/error']]], []
    2019-03-07 23:50:09.777  INFO 6456 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@369ad7da, org.springframework.security.web.context.SecurityContextPersistenceFilter@13c90c06, org.springframework.security.web.header.HeaderWriterFilter@3355168, org.springframework.security.web.authentication.logout.LogoutFilter@2830315f, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@553ce348, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@365bfc5f, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@15f861ee, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@405d8a80, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@344f9467, org.springframework.security.web.session.SessionManagementFilter@580c17a0, org.springframework.security.web.access.ExceptionTranslationFilter@5ba184fc, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@6e364f1f]
    2019-03-07 23:50:09.795  INFO 6456 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/**']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@143413cd, org.springframework.security.web.context.SecurityContextPersistenceFilter@2b5f8e61, org.springframework.security.web.header.HeaderWriterFilter@56f9de3b, org.springframework.security.web.authentication.logout.LogoutFilter@6ec3d8e4, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@1aeff8ca, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@6ba0ee4a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@73b0ed03, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@4b32465, org.springframework.security.web.session.SessionManagementFilter@6728370a, org.springframework.security.web.access.ExceptionTranslationFilter@38ef1a0a, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4af70b83]
    2019-03-07 23:50:10.002  INFO 6456 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
    2019-03-07 23:50:10.011  INFO 6456 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 2147483647
    2019-03-07 23:50:10.054  INFO 6456 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
    2019-03-07 23:50:10.061  INFO 6456 --- [           main] c.o.c.s.s.sandboxmanager.Application     : Started Application in 26.379 seconds (JVM running for 26.819)
    

    The Commandline runner class

       @Component
       public class EventProcessorRunner implements CommandLineRunner{
    
        private final EventProcessor processor; 
    
        EventProcessorRunner(final EventProcessor processor) {
           this.processor = processor;
        }
    
        @Override
        public void run(String... args) throws Exception {
            processor.startProcess();
    
        }
    
    }
    

    Answer:

    The @EnableConfigurationProperties annotation must be used in conjuction with @Configuration annotated classes, not with @Component ones. That's one issue I see immediatly.

    Move that to a @Configuration class, and be sure the EventProcessor Component is correctly scanned.

    Currently the @Autowire of a valid AzureProperties instance would fail.You'll have empty/null properties.


    I wouldn't use @PostConstruct for that, instead CommandLineRunner is better suited.

    @Component
    class EventProcessorRunner implements CommandLineRunner {
        private final EventProcessor processor; 
    
        EventProcessorRunner(final EventProcessor processor) {
           this.processor = processor;
        }
    
        @Override
        public void run(final String... args) throws Exception {
            processor.startProcess();
        }
    }
    

    The @SpringBootApplication annotation already provides a @ComponentScan under the hood. And you can also add @EnableConfigurationProperties

    @SpringBootApplication
    @EnableConfigurationProperties(AzureProperties.class)
    @EnableDatabaseManagement
    @PropertySource(value = "classpath:/secure.properties", ignoreResourceNotFound = true)
    public class Application {
        public static void main(String[] args) throws EventHubException, IOException, InterruptedException, ExecutionException {
            TimeZone.setDefault(TimeZone.getTimeZone("Etc/UCT"));
            DateTimeZone.setDefault(DateTimeZone.forID("Etc/UCT"));
            SpringApplication.run(Application.class, args);
        }
    }
    

    Question:

    I'm using this simple example to run Spring Yarn app against Hadoop on Azure.

    The question is how can I set fs.azure.account.key.aaa.blob.core.windows.net property? Without it Spring YARN cannot deploy my jar file to cluster.

    YarnConfiguration doesn't pick up my yarn-site.xml and core-site.xml files.


    Answer:

    SOLVED

    In application.yml fsUri should be without any ports and other stuff:

    fsUri: wasb://zzz@zzz.blob.core.windows.net
    

    YarnConfiguration picks every config file in resources.