问:
RetroFit maps only half the object Android studio
I have the below response in json

```<code>    {
  "date": 1590656196885,
  "host": "qa1234",
  "api": "v8",
  "response": {
    "type": "PickUp",
    "payload": {
      "serialNumber": "245547105486858"
    }
  }
}
</code>```

This is my response classes

```<code>import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.init.models.Response;

@JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class TransactionsResponseDetails extends ErrorResponse {

        @JsonProperty("date")
        private String date;
        @JsonProperty("host")
        private String host;
        @JsonProperty("api")
        private String api;
        @JsonProperty("response")
        private Response response;

        public TransactionsResponseDetails() {}

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public String getApi() {
            return api;
        }

        public void setApi(String api) {
            this.api = api;
        }

        public Response getResponse() {
            return response;
        }

        public void setResponse(Response response) {
            this.response = response;
        }
    }
</code>```

-

```<code>import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

     @JsonInclude(JsonInclude.Include.NON_NULL)
        @JsonIgnoreProperties(ignoreUnknown = true)
        public class Response {
            @JsonProperty("payload")
            private Payload payload;
            @JsonProperty("type")
            private String type;

            public Response() {}

            public Payload getPayload() {
                return payload;
            }

            public void setPayload(Payload payload) {
                this.payload = payload;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }
        }
</code>```

-

```<code>import com.fasterxml.jackson.annotation.JsonProperty;

    class Payload {
        @JsonProperty("serialNumber")
        private String serialNumber;

        public Payload() {}

        public String getSerialNumber() {
            return serialNumber;
        }
        public void setSerialNumber(String serialNumber) {
            this.serialNumber = serialNumber;
        }
    }
</code>```

and this is the actual call with RetroFit

```<code>import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import com.init.TransactionsResponse;
import com.init.models.responses.TransactionsResponseDetails;
.
.
.
    Call<TransactionsResponseDetails> Rcall = requestInterface.transactionsDetails(transactionResponseModelForTransactionDetails.get(0));
        Rcall.enqueue(new Callback<TransactionsResponseDetails>() {
            @Override
            public void onResponse(Call<TransactionsResponseDetails> call, Response<TransactionsResponseDetails> response) {
                try {
                    TransactionsResponseDetails transactionsResponseDetails;
                    if (response.isSuccessful()) {
                        transactionsResponseDetails = response.body();
                    } else {
                        transactionsResponseDetails = ErrorResponse.parseError(response, TransactionsResponseDetails.class);
                        if (BuildConfig.DEV_STATUS) {
                            Log.d("TransactionsModelError:", transactionsResponseDetails.getErrorModel().getErrorMessage());
                        }
                    }
                } catch (Exception ex) {
                    if (BuildConfig.DEV_STATUS) {
                        ex.printStackTrace();
                    }
                }
</code>```

This is my client

```<code>@Headers({"Content-Type: application/json", "Accept: application/json", BuildConfig.API_BASE_KEY})
@POST("transactions/details")
Call<TransactionsResponseDetails> transactionsDetails(@Body TransactionResponseModelForTransactionDetails transactionResponseModelForTransactionDetails);
</code>```

This is my mapper setup

```<code>OkHttpClient : private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(API_BASE_URL) .addConverterFactory(JacksonConverterFactory.create(getMapper()));

    private static ObjectMapper getMapper(){
        ObjectMapper mapper =  jacksonObjectMapper();
        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);
            return mapper;
        }
</code>```

The call works. I can see the json response in my logs.
The problem is that the mapping only works for  "date" , "host" and "api". No matter what I have tried the "response" object is not mapped. Could you please help me?

答:
Please find my answer below:

Dependencies

com.squareup.okhttp3:okhttp:4.6.0

com.squareup.retrofit2:converter-jackson:2.9.0

com.squareup.retrofit2:retrofit:2.8.1

Retrofit Configuration Java File

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())
                .build();
        // My Local Test Web Server replace with actual host
        final String host = "http://localhost:8080/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(HttpUrl.parse(host))
                .client(client)
                .addConverterFactory(JacksonConverterFactory.create())
                .build();
        TransactionService transactionService = retrofit.create(TransactionService.class);
        transactionService.getTransactionDetailsResponse()
                .enqueue(new Callback<TransactionsResponseDetails>() {
                    @Override
                    public void onResponse(Call<TransactionsResponseDetails> call, retrofit2.Response<TransactionsResponseDetails> response) {
                        System.out.println(response.body().toString());
                    }

                    @Override
                    public void onFailure(Call<TransactionsResponseDetails> call, Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });
```

<p>Logging Interceptor</p>

<pre class="lang-java prettyprint-override"><code>static class LoggingInterceptor implements Interceptor {
        private Logger logger = Logger.getLogger(LoggingInterceptor.class.getSimpleName());

        @Override
        public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
            Request request = chain.request();

            long t1 = System.nanoTime();
            logger.info(String.format("Sending request %s on %s%n%s",
                    request.url(), chain.connection(), request.headers()));

            okhttp3.Response response = chain.proceed(request);

            long t2 = System.nanoTime();
            logger.info(String.format("Received response for %s in %.1fms%n%s",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers()));
            return response;
        }
    }
</code>```

API Interface:

public interface TransactionService {
        // My Local path replace with actual path
        @GET("hello/data")
        Call<TransactionsResponseDetails> getTransactionDetailsResponse();
}
```

I have used your POJO classes as they were hence not posting them.

I Believe your converter is not setup on OkHttpClient. If not please try this answer.

Body:
I have the below response in json

    {
  "date": 1590656196885,
  "host": "qa1234",
  "api": "v8",
  "response": {
    "type": "PickUp",
    "payload": {
      "serialNumber": "245547105486858"
    }
  }
}

This is my response classes

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.init.models.Response;

@JsonInclude(JsonInclude.Include.NON_NULL)
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class TransactionsResponseDetails extends ErrorResponse {

        @JsonProperty("date")
        private String date;
        @JsonProperty("host")
        private String host;
        @JsonProperty("api")
        private String api;
        @JsonProperty("response")
        private Response response;

        public TransactionsResponseDetails() {}

        public String getDate() {
            return date;
        }

        public void setDate(String date) {
            this.date = date;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public String getApi() {
            return api;
        }

        public void setApi(String api) {
            this.api = api;
        }

        public Response getResponse() {
            return response;
        }

        public void setResponse(Response response) {
            this.response = response;
        }
    }

-

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;

     @JsonInclude(JsonInclude.Include.NON_NULL)
        @JsonIgnoreProperties(ignoreUnknown = true)
        public class Response {
            @JsonProperty("payload")
            private Payload payload;
            @JsonProperty("type")
            private String type;

            public Response() {}

            public Payload getPayload() {
                return payload;
            }

            public void setPayload(Payload payload) {
                this.payload = payload;
            }

            public String getType() {
                return type;
            }

            public void setType(String type) {
                this.type = type;
            }
        }

-

import com.fasterxml.jackson.annotation.JsonProperty;

    class Payload {
        @JsonProperty("serialNumber")
        private String serialNumber;

        public Payload() {}

        public String getSerialNumber() {
            return serialNumber;
        }
        public void setSerialNumber(String serialNumber) {
            this.serialNumber = serialNumber;
        }
    }

and this is the actual call with RetroFit

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import com.init.TransactionsResponse;
import com.init.models.responses.TransactionsResponseDetails;
.
.
.
    Call<TransactionsResponseDetails> Rcall = requestInterface.transactionsDetails(transactionResponseModelForTransactionDetails.get(0));
        Rcall.enqueue(new Callback<TransactionsResponseDetails>() {
            @Override
            public void onResponse(Call<TransactionsResponseDetails> call, Response<TransactionsResponseDetails> response) {
                try {
                    TransactionsResponseDetails transactionsResponseDetails;
                    if (response.isSuccessful()) {
                        transactionsResponseDetails = response.body();
                    } else {
                        transactionsResponseDetails = ErrorResponse.parseError(response, TransactionsResponseDetails.class);
                        if (BuildConfig.DEV_STATUS) {
                            Log.d("TransactionsModelError:", transactionsResponseDetails.getErrorModel().getErrorMessage());
                        }
                    }
                } catch (Exception ex) {
                    if (BuildConfig.DEV_STATUS) {
                        ex.printStackTrace();
                    }
                }

This is my client

@Headers({"Content-Type: application/json", "Accept: application/json", BuildConfig.API_BASE_KEY})
@POST("transactions/details")
Call<TransactionsResponseDetails> transactionsDetails(@Body TransactionResponseModelForTransactionDetails transactionResponseModelForTransactionDetails);

This is my mapper setup

OkHttpClient : private static Retrofit.Builder builder = new Retrofit.Builder() .baseUrl(API_BASE_URL) .addConverterFactory(JacksonConverterFactory.create(getMapper()));

    private static ObjectMapper getMapper(){
        ObjectMapper mapper =  jacksonObjectMapper();
        mapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true);
            return mapper;
        }

The call works. I can see the json response in my logs.
The problem is that the mapping only works for  "date" , "host" and "api". No matter what I have tried the "response" object is not mapped. Could you please help me?

Body:
Please find my answer below:

Dependencies

com.squareup.okhttp3:okhttp:4.6.0

com.squareup.retrofit2:converter-jackson:2.9.0

com.squareup.retrofit2:retrofit:2.8.1

Retrofit Configuration Java File

OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new LoggingInterceptor())
                .build();
        // My Local Test Web Server replace with actual host
        final String host = "http://localhost:8080/";

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(HttpUrl.parse(host))
                .client(client)
                .addConverterFactory(JacksonConverterFactory.create())
                .build();
        TransactionService transactionService = retrofit.create(TransactionService.class);
        transactionService.getTransactionDetailsResponse()
                .enqueue(new Callback<TransactionsResponseDetails>() {
                    @Override
                    public void onResponse(Call<TransactionsResponseDetails> call, retrofit2.Response<TransactionsResponseDetails> response) {
                        System.out.println(response.body().toString());
                    }

                    @Override
                    public void onFailure(Call<TransactionsResponseDetails> call, Throwable throwable) {
                        throwable.printStackTrace();
                    }
                });

Logging Interceptor

static class LoggingInterceptor implements Interceptor {
        private Logger logger = Logger.getLogger(LoggingInterceptor.class.getSimpleName());

        @Override
        public okhttp3.Response intercept(Interceptor.Chain chain) throws IOException {
            Request request = chain.request();

            long t1 = System.nanoTime();
            logger.info(String.format("Sending request %s on %s%n%s",
                    request.url(), chain.connection(), request.headers()));

            okhttp3.Response response = chain.proceed(request);

            long t2 = System.nanoTime();
            logger.info(String.format("Received response for %s in %.1fms%n%s",
                    response.request().url(), (t2 - t1) / 1e6d, response.headers()));
            return response;
        }
    }

API Interface:

public interface TransactionService {
        // My Local path replace with actual path
        @GET("hello/data")
        Call<TransactionsResponseDetails> getTransactionDetailsResponse();
}

I have used your POJO classes as they were hence not posting them.

I Believe your converter is not setup on OkHttpClient. If not please try this answer.


来源: stackexchange

问:
Python crazy module import in a package
I'm inside a python package where there is A.py, B.py and an init file that allows me to import packages into the directory above.

Thus, the content of my init file is as follows:

```<code>__path__ = __import__('pkgutil').extend_path(__path__, __name__)
</code>```

I now want to import a class of B.py into A.py. I tried to use from B import myClass but it doesn't work. I also tried to add the file in the path by adding this line to the init file :

```<code>__path__.append(__file__)
</code>```

How to add B.py to the path ?

--edit--

To clarify things, here is the structure of my packages and modules :

```<code>|app.py
|package1
    |__init__.py
    |C.py
    |package2
        |__init__.py
        |A.py
        |B.py
</code>```

In A.py I need to import classes from B.py and C.py

答:
If this is python 3 related code...then really there's no need for an __init__.py anymore.

As long as your files that you want to import classes/functions from are within the same directory you should be able to just call in the file you want to do the import as this:

```<code> import B.myClass
</code>```

or,

```<code> from . import myClass
 ### this imports all the classes and moduels from within the same directory
 ### as you're currently in even if it has more than one file (but only imports myClass)
</code>```

ContentLicense: CC BY-SA 4.0

Title: Python crazy module import in a package

Body:
I'm inside a python package where there is A.py, B.py and an init file that allows me to import packages into the directory above.

Thus, the content of my init file is as follows:

__path__ = __import__('pkgutil').extend_path(__path__, __name__)

I now want to import a class of B.py into A.py. I tried to use from B import myClass but it doesn't work. I also tried to add the file in the path by adding this line to the init file :

__path__.append(__file__)

How to add B.py to the path ?

--edit--

To clarify things, here is the structure of my packages and modules :

|app.py
|package1
    |__init__.py
    |C.py
    |package2
        |__init__.py
        |A.py
        |B.py

In A.py I need to import classes from B.py and C.py

Body:
If this is python 3 related code...then really there's no need for an __init__.py anymore.

As long as your files that you want to import classes/functions from are within the same directory you should be able to just call in the file you want to do the import as this:

 import B.myClass

or,

 from . import myClass
 ### this imports all the classes and moduels from within the same directory
 ### as you're currently in even if it has more than one file (but only imports myClass)


问:
Python - Regex (Re.Escape, Re.Findall); How To: Find sub-strings + a number of characters beyond the sub-strings within a string?
This might be an simple question.  I'm learning how to use Regex and I am having trouble performing a specific task on a string.

For example:

example_string = "; One, one; Two, two; Three, three; Four, four"

desired_output = ["One, o", "Two, t", "Three, t", "Four, f"] #list output is OK

With the following, i can get ["One" , "Two" , "Three"]:

```<code>def findStringsInMiddle(a, b, text):
    return re.findall(re.escape(a)+"(.*?)"+re.escape(b),text)

desired_output = findStringsInMiddle('; ' , ',' , example_string)
</code>```

But I am having trouble figuring out how to configure this properly to grab the comma+space+any_type_of_character that I also want.

Any advice?

Thanks!

答:
You can set the full pattern (from semi-colon to the second letter after the comma) and mark the group you want to extract:</p>

```<code>>>> s =  "; One, one; Two, two; Three, three; Four, four"
>>> re.findall(r"; (.*?,.{2})", s)
['One, o', 'Two, t', 'Three, t', 'Four, f']
</code>```

Body:
This might be an simple question.  I'm learning how to use Regex and I am having trouble performing a specific task on a string.

For example:

example_string = "; One, one; Two, two; Three, three; Four, four"

desired_output = ["One, o", "Two, t", "Three, t", "Four, f"] #list output is OK

With the following, i can get ["One" , "Two" , "Three"]:

def findStringsInMiddle(a, b, text):
    return re.findall(re.escape(a)+"(.*?)"+re.escape(b),text)

desired_output = findStringsInMiddle('; ' , ',' , example_string)

But I am having trouble figuring out how to configure this properly to grab the comma+space+any_type_of_character that I also want.

Any advice?

Thanks!

Body:
You can set the full pattern (from semi-colon to the second letter after the comma) and mark the group you want to extract:

>>> s =  "; One, one; Two, two; Three, three; Four, four"
>>> re.findall(r"; (.*?,.{2})", s)
['One, o', 'Two, t', 'Three, t', 'Four, f']


问:
How can I find the location of origin/master in git, and how do I change it?
I'm a Git newbie.  I recently moved a Rails project from Subversion to Git.  I followed the tutorial here: http://www.simplisticcomplexity.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository/

I am also using unfuddle.com to store my code.  I make changes on my Mac laptop on the train to/from work and then push them to unfuddle when I have a network connection using the following command:

```<code>git push unfuddle master
</code>```

I use Capistrano for deployments and pull code from the unfuddle repository using the master branch.

Lately I've noticed the following message when I run "git status" on my laptop:

```<code># On branch master
# Your branch is ahead of 'origin/master' by 11 commits.
#
nothing to commit (working directory clean)
</code>```

And I'm confused as to why.  I thought my laptop was the origin... but don't know if either the fact that I originally pulled from Subversion or push to Unfuddle is what's causing the message to show up.  How can I:

Find out where Git thinks 'origin/master' is?

If it's somewhere else, how do I turn my laptop into the 'origin/master'?

Get this message to go away. It makes me think Git is unhappy about something.

My mac is running Git version 1.6.0.1.

When I run git remote show origin as suggested by dbr, I get the following:

```<code>~/Projects/GeekFor/geekfor 10:47 AM $ git remote show origin
fatal: '/Users/brian/Projects/GeekFor/gf/.git': unable to chdir or not a git archive
fatal: The remote end hung up unexpectedly
</code>```

When I run git remote -v as suggested by Aristotle Pagaltzis, I get the following:

```<code>~/Projects/GeekFor/geekfor 10:33 AM $ git remote -v
origin  /Users/brian/Projects/GeekFor/gf/.git
unfuddle    git@spilth.unfuddle.com:spilth/geekfor.git
</code>```

Now, interestingly, I'm working on my project in the geekfor directory but it says my origin is my local machine in the gf directory.  I believe gf was the temporary directory I used when converting my project from Subversion to Git and probably where I pushed to unfuddle from.  Then I believe I checked out a fresh copy from unfuddle to the geekfor directory.

So it looks like I should follow dbr's advice and do:

```<code>git remote rm origin
git remote add origin git@spilth.unfuddle.com:spilth/geekfor.git
</code>```

答:
[ Solution ]

```<code>$ git push origin
</code>```

^ this solved it for me.
What it did, it synchronized my master (on laptop) with "origin" that's on the remote server.

OwnerDisplayName: spilth

ContentLicense: CC BY-SA 3.0

Body:
I'm a Git newbie.  I recently moved a Rails project from Subversion to Git.  I followed the tutorial here: http://www.simplisticcomplexity.com/2008/03/05/cleanly-migrate-your-subversion-repository-to-a-git-repository/

I am also using unfuddle.com to store my code.  I make changes on my Mac laptop on the train to/from work and then push them to unfuddle when I have a network connection using the following command:

git push unfuddle master

I use Capistrano for deployments and pull code from the unfuddle repository using the master branch.

Lately I've noticed the following message when I run "git status" on my laptop:

# On branch master
# Your branch is ahead of 'origin/master' by 11 commits.
#
nothing to commit (working directory clean)

And I'm confused as to why.  I thought my laptop was the origin... but don't know if either the fact that I originally pulled from Subversion or push to Unfuddle is what's causing the message to show up.  How can I:

Find out where Git thinks 'origin/master' is?

If it's somewhere else, how do I turn my laptop into the 'origin/master'?

Get this message to go away. It makes me think Git is unhappy about something.

My mac is running Git version 1.6.0.1.

When I run git remote show origin as suggested by dbr, I get the following:

~/Projects/GeekFor/geekfor 10:47 AM $ git remote show origin
fatal: '/Users/brian/Projects/GeekFor/gf/.git': unable to chdir or not a git archive
fatal: The remote end hung up unexpectedly

When I run git remote -v as suggested by Aristotle Pagaltzis, I get the following:

~/Projects/GeekFor/geekfor 10:33 AM $ git remote -v
origin  /Users/brian/Projects/GeekFor/gf/.git
unfuddle    git@spilth.unfuddle.com:spilth/geekfor.git

Now, interestingly, I'm working on my project in the geekfor directory but it says my origin is my local machine in the gf directory.  I believe gf was the temporary directory I used when converting my project from Subversion to Git and probably where I pushed to unfuddle from.  Then I believe I checked out a fresh copy from unfuddle to the geekfor directory.

So it looks like I should follow dbr's advice and do:

git remote rm origin
git remote add origin git@spilth.unfuddle.com:spilth/geekfor.git

LastEditorDisplayName: spilth

Body:
[ Solution ]

$ git push origin

^ this solved it for me.
What it did, it synchronized my master (on laptop) with "origin" that's on the remote server.


问:
Angular function relies on result of async function

Setup:

I have a function, isAuthorized(), in a singleton, AuthSessionSingleton which relies on the result of an async function.

The async function is an api call, called in the constructor, which expects the return of an object. isAuthorized() relies on that object.

Issue:

Some component calls the function isAuthorized() immediately, before the backend call resolves.
I want to be able to wait inside the isAuthorized() function until the backend call resolves and the object is no longer null.

Simple Code:

//auth.singleton.ts
@Injectable({providedIn: 'root'})
export class AuthSessionSingleton {
  userInfo: UserInfo = null;
  constructor(private service: MyService) {
    this.loadUserInfo();
  }

  loadUserInfo() {
    this.service.makeBackendCall().subscribe({
      next: (obj: UserInfo) => {
        this.userInfo = obj;
      }
    });
  }

  isAuthorized() {
    if(this.userInfo == null) {
      // do something to wait asynchronously
    }

    // Very simple example
    if(this.userInfo.Role == 'Admin') {
      return true;
    }
    return false;
  }
}
```
<pre class="lang-js prettyprint-override"><code>//some.component.ts
export class SomeComponent {
  authorized: boolean = false;

  constructor(private auth: AuthSessionSingleton) {
    this.checkAuthorization();
  }

  async checkAuthorization() {
    this.authorized = await this.auth.isAuthorized();
  }
}
</code>```

In the above simplified program, SomeComponent calling isAuthorized() will likely check userInfo while it is still null. I need to wait for it to not be null.

Possible Solutions:

There are many solutions I've determined so far. I'm looking for the most correct solution and hopefully one that I haven't even thought of.

1. Listen to Subscription

In isAuthorized(), if(this.userInfo==null) subscribe to the same subscription made in loadUserInfo() and wait on it.

2. Wait Until Signaled

I could create a Subject in AuthSessionSingleton and Subscribe from SomeComponent, wait until I get a signal, then call IsAuthorized().

This seems especially roundabout.

3. Just Wait

There are many ways I could just spin my gears until the object I need is no longer null.

while(this.userInfo == null) {
  // do something
}
```
<hr />
<h1>Request:</h1>
<p>I want a way to wait asynchronously in <code>isAuthorized()</code> until <code>this.userInfo != null</code>. Any number of calls can be made to <code>isAuthorized()</code> (from different components) and all of them should wait until that value is resolved.</p>
<p>Any ideas?</p>
<hr />
<h1>Edit</h1>
<p>A more accurate use-case which I now realize changes the possible solutions follows. It is made more complex by accepting an array of values to loop through.</p>
<pre class="lang-js prettyprint-override"><code>isAuthorized(roles: string[]) {
  let(i = 0; i < roles.length; i++) {
    let role = roles[i];
    if(this.userInfo.Role == role) {
      return true;
    }
    return false;
  }
}
</code>```

答:
When there is one async operation involved, you could make all it's dependents asynchronous. Try the following

auth.singleton.ts

@Injectable({providedIn: 'root'})
export class AuthSessionSingleton {
  userInfo = new BehaviorSubject<UserInfo>(null);

  constructor(private service: MyService) {
    this.loadUserInfo();
  }

  loadUserInfo() {
    this.service.makeBackendCall().subscribe({
      next: (obj: UserInfo) => {
        this.userInfo.next(obj);
      }
    });
  }

  isAuthorized() {
    const result = new Subject<boolean>();

    this.userInfo.pipe(take(1)).subscribe(
      userInfo => {
        if (userInfo == 'Admin') {
          result.next(true);
        } else {
          result.next(false)
        }
      }
    );

    return result.asObservable();
}
```

<p>Now you could subscribe to the <code>isAuthorized()</code> function in the components. You could also expose <code>userInfo</code> to check authorization in the component as well.</p>

<p>Component</p>

<pre class="lang-js prettyprint-override"><code>ngOnInit() {
  this.authService.isAuthorized().subscribe(
    status => {
      if (status) {
        // authorized
      } else {
        // unauthorized
      }
    }
  );
}
</code>```

As mentioned in the comments, I wouldn't prefer solutions 1 and 2 for the following reasons

Solution 1: The subscription could trigger an additional unwanted HTTP request.

Solution 3: Could potentially lead to an infinite loop if the back-end doesn't reply.

Body:
Setup:

I have a function, isAuthorized(), in a singleton, AuthSessionSingleton which relies on the result of an async function.

The async function is an api call, called in the constructor, which expects the return of an object. isAuthorized() relies on that object.

Issue:

Some component calls the function isAuthorized() immediately, before the backend call resolves.
I want to be able to wait inside the isAuthorized() function until the backend call resolves and the object is no longer null.

Simple Code:

//auth.singleton.ts
@Injectable({providedIn: 'root'})
export class AuthSessionSingleton {
  userInfo: UserInfo = null;
  constructor(private service: MyService) {
    this.loadUserInfo();
  }

  loadUserInfo() {
    this.service.makeBackendCall().subscribe({
      next: (obj: UserInfo) => {
        this.userInfo = obj;
      }
    });
  }

  isAuthorized() {
    if(this.userInfo == null) {
      // do something to wait asynchronously
    }

    // Very simple example
    if(this.userInfo.Role == 'Admin') {
      return true;
    }
    return false;
  }
}

//some.component.ts
export class SomeComponent {
  authorized: boolean = false;

  constructor(private auth: AuthSessionSingleton) {
    this.checkAuthorization();
  }

  async checkAuthorization() {
    this.authorized = await this.auth.isAuthorized();
  }
}

In the above simplified program, SomeComponent calling isAuthorized() will likely check userInfo while it is still null. I need to wait for it to not be null.

Possible Solutions:

There are many solutions I've determined so far. I'm looking for the most correct solution and hopefully one that I haven't even thought of.

1. Listen to Subscription

In isAuthorized(), if(this.userInfo==null) subscribe to the same subscription made in loadUserInfo() and wait on it.

2. Wait Until Signaled

I could create a Subject in AuthSessionSingleton and Subscribe from SomeComponent, wait until I get a signal, then call IsAuthorized().

This seems especially roundabout.

3. Just Wait

There are many ways I could just spin my gears until the object I need is no longer null.

while(this.userInfo == null) {
  // do something
}

Request:

I want a way to wait asynchronously in isAuthorized() until this.userInfo != null. Any number of calls can be made to isAuthorized() (from different components) and all of them should wait until that value is resolved.

Any ideas?

Edit

A more accurate use-case which I now realize changes the possible solutions follows. It is made more complex by accepting an array of values to loop through.

isAuthorized(roles: string[]) {
  let(i = 0; i < roles.length; i++) {
    let role = roles[i];
    if(this.userInfo.Role == role) {
      return true;
    }
    return false;
  }
}

Body:
When there is one async operation involved, you could make all it's dependents asynchronous. Try the following

auth.singleton.ts

@Injectable({providedIn: 'root'})
export class AuthSessionSingleton {
  userInfo = new BehaviorSubject<UserInfo>(null);

  constructor(private service: MyService) {
    this.loadUserInfo();
  }

  loadUserInfo() {
    this.service.makeBackendCall().subscribe({
      next: (obj: UserInfo) => {
        this.userInfo.next(obj);
      }
    });
  }

  isAuthorized() {
    const result = new Subject<boolean>();

    this.userInfo.pipe(take(1)).subscribe(
      userInfo => {
        if (userInfo == 'Admin') {
          result.next(true);
        } else {
          result.next(false)
        }
      }
    );

    return result.asObservable();
}

Now you could subscribe to the isAuthorized() function in the components. You could also expose userInfo to check authorization in the component as well.

Component

ngOnInit() {
  this.authService.isAuthorized().subscribe(
    status => {
      if (status) {
        // authorized
      } else {
        // unauthorized
      }
    }
  );
}

As mentioned in the comments, I wouldn't prefer solutions 1 and 2 for the following reasons

Solution 1: The subscription could trigger an additional unwanted HTTP request.

Solution 3: Could potentially lead to an infinite loop if the back-end doesn't reply.


问:
ORACLE NLS_LANG
How set and check NLS_LANG settings? I did

```<code>set NLS_LANG = DANISH_DENMARK.WE8ISO8859P2
</code>```

in command prompt but I don't know if it is correct.

答:
If you're on Windows type set at the command line and it will dump out all the environment variables which have been set up.

Note that under Windows, environment variables which are set at the command line in a command line process are not seen by anything except that command line process. If you want to create a permanent environment variable - one which is remembered and used by all other processes - you'll need to go to Control Panel - System - Advanced System Settings - click on the "Environment Variables" button towards the bottom of the dialog - create the variable and value you want in the "System Variables" pane (the lower one on the dialog), and click "OK" to save your changes. To check, open a new Command Line window, type "set" at the command prompt, and verify that the variable you just set is shown in the list with the correct value.

Title: ORACLE NLS_LANG

Body:
How set and check NLS_LANG settings? I did

set NLS_LANG = DANISH_DENMARK.WE8ISO8859P2

in command prompt but I don't know if it is correct.


问:
How do i make a function in my .bash_profile accept input from stdin using pipe |
say i have a function of this nature in my .bash_profile

```<code>sayword(){
   echo $1
}
</code>```

now the command will be run like sayword hello
now i want the function to be able to  take input from other command using  unix pipe. something  like cat words.txt | sayword and it outputs each of the word in words.txt. How do i do that ?. I read a question here that talks about redirecting to dev/null but that doesn't seem to work .

答:
This is where you want the -t condition: that can test if stdin is a pipe/redirection or the terminal (i.e. interactive):

sayword() {
  {
    echo "$(date) - saying words"
    if [ -t 0 ]; then
      # stdin is the terminal: take input from the cmdline parameters:
      echo "$*"
    else
      # stdin is a pipe or redirection
      cat
    fi
  } >> "$HOME/words.txt"
}
```

<p>Then, these both append to the file:</p>

<pre class="lang-sh prettyprint-override"><code>$ sayword hello
$ cat ~/words.txt
Thu May 28 09:22:27 EDT 2020 - saying words
hello
</code>```

$ echo foo bar | sayword
$ cat ~/words.txt
Thu May 28 09:22:27 EDT 2020 - saying words
hello
Thu May 28 09:22:37 EDT 2020 - saying words
foo bar
```

Body:
say i have a function of this nature in my .bash_profile

sayword(){
   echo $1
}

now the command will be run like sayword hello
now i want the function to be able to  take input from other command using  unix pipe. something  like cat words.txt | sayword and it outputs each of the word in words.txt. How do i do that ?. I read a question here that talks about redirecting to dev/null but that doesn't seem to work .

Body:
This is where you want the -t condition: that can test if stdin is a pipe/redirection or the terminal (i.e. interactive):

sayword() {
  {
    echo "$(date) - saying words"
    if [ -t 0 ]; then
      # stdin is the terminal: take input from the cmdline parameters:
      echo "$*"
    else
      # stdin is a pipe or redirection
      cat
    fi
  } >> "$HOME/words.txt"
}

Then, these both append to the file:

$ sayword hello
$ cat ~/words.txt
Thu May 28 09:22:27 EDT 2020 - saying words
hello

$ echo foo bar | sayword
$ cat ~/words.txt
Thu May 28 09:22:27 EDT 2020 - saying words
hello
Thu May 28 09:22:37 EDT 2020 - saying words
foo bar


问:
Convert HTML5 Canvas Sequence to a Video File
I'd like to convert an animation in HTML5 canvas to a video file that could be uploaded to YouTube. Is there any sort of screen capture API or something that could allow me to do this programatically?</p>

答:
Back to 2020

Solved it by using MediaRecorder API. It builds exactly to do that, among other things.

Here is a solution that recorded X ms of canvas video
you can extend it with Buttons UI to start, pause, resume, stop, generate URL.

function record(canvas, time) {
    var recordedChunks = [];
    return new Promise(function (res, rej) {
        var stream = canvas.captureStream(25 /*fps*/);
        mediaRecorder = new MediaRecorder(stream, {
            mimeType: "video/webm; codecs=vp9"
        });

        //ondataavailable will fire in interval of `time || 4000 ms`
        mediaRecorder.start(time || 4000);

        mediaRecorder.ondataavailable = function (event) {
            recordedChunks.push(event.data);
             // after stop `dataavilable` event run one more time
            if (mediaRecorder.state === 'recording') {
                mediaRecorder.stop();
            }

        }

        mediaRecorder.onstop = function (event) {
            var blob = new Blob(recordedChunks, {type: "video/webm" });
            var url = URL.createObjectURL(blob);
            res(url);
        }
    })
}

```
<p>How to use:</p>
<pre class="lang-js prettyprint-override"><code>const recording = record(canvas, 10000)
// play it on another video element
var video$ = document.createElement('video')
document.body.appendChild(video$)
recording.then(url => video$.setAttribute('src', url) )

// download it
var link$ = document.createElement('a')
link$.setAttribute('download','recordingVideo')
recording.then(url => {
 link$.setAttribute('href', url)
 link$.click()
})

</code>```

Body:
Back to 2020

Solved it by using MediaRecorder API. It builds exactly to do that, among other things.

Here is a solution that recorded X ms of canvas video
you can extend it with Buttons UI to start, pause, resume, stop, generate URL.

function record(canvas, time) {
    var recordedChunks = [];
    return new Promise(function (res, rej) {
        var stream = canvas.captureStream(25 /*fps*/);
        mediaRecorder = new MediaRecorder(stream, {
            mimeType: "video/webm; codecs=vp9"
        });

        //ondataavailable will fire in interval of `time || 4000 ms`
        mediaRecorder.start(time || 4000);

        mediaRecorder.ondataavailable = function (event) {
            recordedChunks.push(event.data);
             // after stop `dataavilable` event run one more time
            if (mediaRecorder.state === 'recording') {
                mediaRecorder.stop();
            }

        }

        mediaRecorder.onstop = function (event) {
            var blob = new Blob(recordedChunks, {type: "video/webm" });
            var url = URL.createObjectURL(blob);
            res(url);
        }
    })
}

How to use:

const recording = record(canvas, 10000)
// play it on another video element
var video$ = document.createElement('video')
document.body.appendChild(video$)
recording.then(url => video$.setAttribute('src', url) )

// download it
var link$ = document.createElement('a')
link$.setAttribute('download','recordingVideo')
recording.then(url => {
 link$.setAttribute('href', url)
 link$.click()
})


问:
Kotlin coroutines - delay, how does it work?
I am quite used to using RX to handle concurrency, but, in my current job, we have a mix of AsyncTask, Executors + Handlers, Threads and some LiveData thrown in. Now we are thinking about moving towards using Kotlin Coroutines (and in fact have started using it in certain places in the codebase).

Therefore, I need to start wrapping my head around Coroutines, ideally drawing from my existing knowledge of concurrency tools to speed the process up.

I have tried following the Google codelab for them and whilst it's giving me a bit of understanding it's also raising lots of unanswered questions so I've tried getting my hands dirty by writing some code, debugging and looking at log outputs.

As I understand it, a coroutine is composed of 2 main building blocks; suspend functions which are where you do your work and coroutine contexts which is where you execute suspend functions such that you can have a handle on what dispatchers the coroutines will run on.

Here I have some code below, that behaves as I would expect. I have set up a coroutine context using Dispatchers.Main. So, as expected, when I launch the coroutine getResources it ends up blocking the UI thread for 5 seconds due to the Thread.sleep(5000):

```<code>private const val TAG = "Coroutines"

class MainActivity : AppCompatActivity(), CoroutineScope {
    override val coroutineContext: CoroutineContext = Job() + Dispatchers.Main

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        log("onCreate", "launching coroutine")
        launch {
            val resource = getResource()
            log("onCreate", "resource fetched: $resource")
            findViewById<TextView>(R.id.textView).text = resource.toString()
        }
        log("onCreate", "coroutine launched")
    }

    private suspend fun getResource() : Int {
        log("getResource", "about to sleep for 5000ms")
        Thread.sleep(5000)
        log("getResource", "finished fetching resource")
        return 1
    }

    private fun log(methodName: String, toLog: String) {
        Log.d(TAG,"$methodName: $toLog: ${Thread.currentThread().name}")
    }
}
</code>```

When I run this code, I see the following logs:

```<code>2020-05-28 11:42:44.364 9819-9819/? D/Coroutines: onCreate: launching coroutine: main
2020-05-28 11:42:44.376 9819-9819/? D/Coroutines: onCreate: coroutine launched: main
2020-05-28 11:42:44.469 9819-9819/? D/Coroutines: getResource: about to sleep for 5000ms: main
2020-05-28 11:42:49.471 9819-9819/com.example.coroutines D/Coroutines: getResource: finished fetching resource: main
2020-05-28 11:42:49.472 9819-9819/com.example.coroutines D/Coroutines: onCreate: resource fetched: 1: main
</code>```

As you can see, all the logs originated from the main thread, and there is a 5 second gap between the log before and after the Thread.sleep(5000). During that 5 second gap, the UI thread is blocked, I can confirm this by just looking at the emulator; it doens't render any UI because onCreate is blocked.

Now, if I update the getResources function to use the suspend fun delay(5000) instead of using Thread.sleep(5000) like so:

```<code>private suspend fun getResource() : Int {
    log("getResource", "about to sleep for 5000ms")
    delay(5000)
    log("getResource", "finished fetching resource")
    return 1
}
</code>```

Then what I end up seeing confuses me. I understand delay isn't the same as Thread.sleep, but because I am running it within the coroutine context which is backed by Dispatchers.Main, I expected to see the same result as using Thread.sleep.

Instead, what I see is the UI thread is not blocked while the 5 second delay is happening, and the logs look like:

```<code>2020-05-28 11:54:19.099 10038-10038/com.example.coroutines D/Coroutines: onCreate: launching coroutine: main
2020-05-28 11:54:19.111 10038-10038/com.example.coroutines D/Coroutines: onCreate: coroutine launched: main
2020-05-28 11:54:19.152 10038-10038/com.example.coroutines D/Coroutines: getResource: about to sleep for 5000ms: main
2020-05-28 11:54:24.167 10038-10038/com.example.coroutines D/Coroutines: getResource: finished fetching resource: main
2020-05-28 11:54:24.168 10038-10038/com.example.coroutines D/Coroutines: onCreate: resource fetched: 1: main
</code>```

I can see the UI thread is not blocked in this case as the UI renders whilst the delay is taking place and then the text view is updated after 5 seconds.

So, my question is, how does delay, in this case, not block the UI thread (even though the logs in my suspend function still indicate that the function is running on the main thread...)

答:
Think of suspend functions as a way to use a function that takes a callback, but doesn't require you to to pass that callback into it. Instead, the callback code is everything under the suspend function call.

This code:

```<code>lifecycleScope.launch {
    myTextView.text = "Starting"
    delay(1000L)
    myTextView.text = "Processing"
    delay(2000L)
    myTextView.text = "Done"
}
</code>```

Is somewhat like:

```<code>myTextView.text = "Starting"
handler.postDelayed(1000L) {
    myTextView.text = "Processing"
    handler.postDelayed(2000L) {
        myTextView.text = "Done"
    }
}
</code>```

Suspend functions should never be expected to block. If they do, they have been composed incorrectly. Any blocking code in a suspend function should be wrapped in something that backgrounds it, like withContext or suspendCancellableCoroutine (which is lower level because it works directly with the coroutine continuation).

If you try to write a suspend function like this:

```<code>suspend fun myDelay(length: Long) {
    Thread.sleep(length)
}
</code>```

you will get a compiler warning for "Inappropriate blocking method call". If you push it to a background dispatcher, you won't get the warning:

```<code>suspend fun myDelay(length: Long) = withContext(Dispatchers.IO) {
    Thread.sleep(length)
}
</code>```

If you try to send it to Dispatchers.Main, you will get the warning again, because the compiler considers any blocking code on the Main thread to be incorrect.

This should give you and idea of how a suspend function should operate, but keep in mind the compiler cannot always recognize a method call as blocking.

Body:
I am quite used to using RX to handle concurrency, but, in my current job, we have a mix of AsyncTask, Executors + Handlers, Threads and some LiveData thrown in. Now we are thinking about moving towards using Kotlin Coroutines (and in fact have started using it in certain places in the codebase).

Therefore, I need to start wrapping my head around Coroutines, ideally drawing from my existing knowledge of concurrency tools to speed the process up.

I have tried following the Google codelab for them and whilst it's giving me a bit of understanding it's also raising lots of unanswered questions so I've tried getting my hands dirty by writing some code, debugging and looking at log outputs.

As I understand it, a coroutine is composed of 2 main building blocks; suspend functions which are where you do your work and coroutine contexts which is where you execute suspend functions such that you can have a handle on what dispatchers the coroutines will run on.

Here I have some code below, that behaves as I would expect. I have set up a coroutine context using Dispatchers.Main. So, as expected, when I launch the coroutine getResources it ends up blocking the UI thread for 5 seconds due to the Thread.sleep(5000):

private const val TAG = "Coroutines"

class MainActivity : AppCompatActivity(), CoroutineScope {
    override val coroutineContext: CoroutineContext = Job() + Dispatchers.Main

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        log("onCreate", "launching coroutine")
        launch {
            val resource = getResource()
            log("onCreate", "resource fetched: $resource")
            findViewById<TextView>(R.id.textView).text = resource.toString()
        }
        log("onCreate", "coroutine launched")
    }

    private suspend fun getResource() : Int {
        log("getResource", "about to sleep for 5000ms")
        Thread.sleep(5000)
        log("getResource", "finished fetching resource")
        return 1
    }

    private fun log(methodName: String, toLog: String) {
        Log.d(TAG,"$methodName: $toLog: ${Thread.currentThread().name}")
    }
}

When I run this code, I see the following logs:

2020-05-28 11:42:44.364 9819-9819/? D/Coroutines: onCreate: launching coroutine: main
2020-05-28 11:42:44.376 9819-9819/? D/Coroutines: onCreate: coroutine launched: main
2020-05-28 11:42:44.469 9819-9819/? D/Coroutines: getResource: about to sleep for 5000ms: main
2020-05-28 11:42:49.471 9819-9819/com.example.coroutines D/Coroutines: getResource: finished fetching resource: main
2020-05-28 11:42:49.472 9819-9819/com.example.coroutines D/Coroutines: onCreate: resource fetched: 1: main

As you can see, all the logs originated from the main thread, and there is a 5 second gap between the log before and after the Thread.sleep(5000). During that 5 second gap, the UI thread is blocked, I can confirm this by just looking at the emulator; it doens't render any UI because onCreate is blocked.

Now, if I update the getResources function to use the suspend fun delay(5000) instead of using Thread.sleep(5000) like so:

private suspend fun getResource() : Int {
    log("getResource", "about to sleep for 5000ms")
    delay(5000)
    log("getResource", "finished fetching resource")
    return 1
}

Then what I end up seeing confuses me. I understand delay isn't the same as Thread.sleep, but because I am running it within the coroutine context which is backed by Dispatchers.Main, I expected to see the same result as using Thread.sleep.

Instead, what I see is the UI thread is not blocked while the 5 second delay is happening, and the logs look like:

2020-05-28 11:54:19.099 10038-10038/com.example.coroutines D/Coroutines: onCreate: launching coroutine: main
2020-05-28 11:54:19.111 10038-10038/com.example.coroutines D/Coroutines: onCreate: coroutine launched: main
2020-05-28 11:54:19.152 10038-10038/com.example.coroutines D/Coroutines: getResource: about to sleep for 5000ms: main
2020-05-28 11:54:24.167 10038-10038/com.example.coroutines D/Coroutines: getResource: finished fetching resource: main
2020-05-28 11:54:24.168 10038-10038/com.example.coroutines D/Coroutines: onCreate: resource fetched: 1: main

I can see the UI thread is not blocked in this case as the UI renders whilst the delay is taking place and then the text view is updated after 5 seconds.

So, my question is, how does delay, in this case, not block the UI thread (even though the logs in my suspend function still indicate that the function is running on the main thread...)

Body:
Think of suspend functions as a way to use a function that takes a callback, but doesn't require you to to pass that callback into it. Instead, the callback code is everything under the suspend function call.

This code:

lifecycleScope.launch {
    myTextView.text = "Starting"
    delay(1000L)
    myTextView.text = "Processing"
    delay(2000L)
    myTextView.text = "Done"
}

Is somewhat like:

myTextView.text = "Starting"
handler.postDelayed(1000L) {
    myTextView.text = "Processing"
    handler.postDelayed(2000L) {
        myTextView.text = "Done"
    }
}

Suspend functions should never be expected to block. If they do, they have been composed incorrectly. Any blocking code in a suspend function should be wrapped in something that backgrounds it, like withContext or suspendCancellableCoroutine (which is lower level because it works directly with the coroutine continuation).

If you try to write a suspend function like this:

suspend fun myDelay(length: Long) {
    Thread.sleep(length)
}

you will get a compiler warning for "Inappropriate blocking method call". If you push it to a background dispatcher, you won't get the warning:

suspend fun myDelay(length: Long) = withContext(Dispatchers.IO) {
    Thread.sleep(length)
}

If you try to send it to Dispatchers.Main, you will get the warning again, because the compiler considers any blocking code on the Main thread to be incorrect.

This should give you and idea of how a suspend function should operate, but keep in mind the compiler cannot always recognize a method call as blocking.


问:
How to write avro to multiple output directory using spark
Hi，There is a topic about writing text data into multiple output directories in one spark job using MultipleTextOutputFormat

Write to multiple outputs by key Spark - one Spark job

I would ask if there is some similar way to write avro data to multiple directories

What I want is to write the data in avro file to different directory(based on the timestamp field, same day in the timestamp goes to the same directory)

答:
Here is what we had implemented for our usecase in java : Write to different files with prefix depending upon the content of avro record using AvroMultipleOutputs.

Here is the wrapper on top of OutputFormat to produce multiple outputs using AvroMultipleOutputs similar to what @Ram has mentioned. https://github.com/architch/MultipleAvroOutputsFormat/blob/master/MultipleAvroOutputsFormat.java

It can be used to  write avro records to multiple paths in spark the following way:

```<code>Job job = Job.getInstance(hadoopConf);
AvroJob.setOutputKeySchema(job, schema);
AvroMultipleOutputs.addNamedOutput(job,"type1",AvroKeyOutputFormat.class,schema);
AvroMultipleOutputs.addNamedOutput(job,"type2",AvroKeyOutputFormat.class,schema);

rdd.mapToPair(event->{
            if(event.isType1())
                return new Tuple2<>(new Tuple2<>("type1",new AvroKey<>(event.getRecord())),NullWritable.get());
            else
                return new Tuple2<>(new Tuple2<>("type2",new AvroKey<>(event.getRecord())),NullWritable.get());
                })
             .saveAsNewAPIHadoopFile(
                        outputBasePath,
                        GenericData.Record.class,
                        NullWritable.class,
                        MultipleAvroOutputsFormat.class,
                        job.getConfiguration()
                );
</code>```

Here getRecords returns a GenericRecord.
The output would be like this at outputBasePath:

```<code>17359 May 28 15:23 type1-r-00000.avro
28029 May 28 15:24 type1-r-00001.avro
16473 May 28 15:24 type1-r-00003.avro
17124 May 28 15:23 type2-r-00000.avro
30962 May 28 15:24 type2-r-00001.avro
16229 May 28 15:24 type2-r-00003.avro
</code>```

This can also be used to write to different directories altogether by providing the baseOutputPath directly as mentioned here: write to multiple directory

Body:
Here is what we had implemented for our usecase in java : Write to different files with prefix depending upon the content of avro record using AvroMultipleOutputs.

Here is the wrapper on top of OutputFormat to produce multiple outputs using AvroMultipleOutputs similar to what @Ram has mentioned. https://github.com/architch/MultipleAvroOutputsFormat/blob/master/MultipleAvroOutputsFormat.java

It can be used to  write avro records to multiple paths in spark the following way:

Job job = Job.getInstance(hadoopConf);
AvroJob.setOutputKeySchema(job, schema);
AvroMultipleOutputs.addNamedOutput(job,"type1",AvroKeyOutputFormat.class,schema);
AvroMultipleOutputs.addNamedOutput(job,"type2",AvroKeyOutputFormat.class,schema);

rdd.mapToPair(event->{
            if(event.isType1())
                return new Tuple2<>(new Tuple2<>("type1",new AvroKey<>(event.getRecord())),NullWritable.get());
            else
                return new Tuple2<>(new Tuple2<>("type2",new AvroKey<>(event.getRecord())),NullWritable.get());
                })
             .saveAsNewAPIHadoopFile(
                        outputBasePath,
                        GenericData.Record.class,
                        NullWritable.class,
                        MultipleAvroOutputsFormat.class,
                        job.getConfiguration()
                );

Here getRecords returns a GenericRecord.
The output would be like this at outputBasePath:

17359 May 28 15:23 type1-r-00000.avro
28029 May 28 15:24 type1-r-00001.avro
16473 May 28 15:24 type1-r-00003.avro
17124 May 28 15:23 type2-r-00000.avro
30962 May 28 15:24 type2-r-00001.avro
16229 May 28 15:24 type2-r-00003.avro

This can also be used to write to different directories altogether by providing the baseOutputPath directly as mentioned here: write to multiple directory


问:
React Native Button Icon not showing
I am using expo's snack, no icon ever showing correctly, what am I doing wrong?
I test this snack https://callstack.github.io/react-native-paper/button.html, and many other snack, but it always show rectangle icon.

I am using expo 36.0.0

答:
The issue is visible in expo log as

Tried to use the icon 'stepforward' in a component from 'react-native-paper', but 'react-native-vector-icons' could not be loaded.
  To remove this warning, try installing 'react-native-vector-icons' or use another method to specify icon: https://callstack.github.io/react-native-paper/icons.html.
  Even if you try to add package it's still not resolved by this, some issue in expo as reported here Expo forums

Following is the workaround as Snack link

Using Expo vector Icon

```<code>import { Ionicons } from '@expo/vector-icons';
</code>```

2.Get type

```<code>import SimpleIcon from 'react-native-vector-icons/SimpleLineIcons';

import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
</code>```

then pass as child

Title: React Native Button Icon not showing

Body:
I am using expo's snack, no icon ever showing correctly, what am I doing wrong?
I test this snack <a href="https://snack.expo.io/?name=Button&description=https%3A%2F%2Fcallstack.github.io%2Freact-native-paper%2Fbutton.html&code=import%20*%20as%20React%20from%20%27react%27%3B%0Aimport%20%7B%20Button%20%7D%20from%20%27react-native-paper%27%3B%0A%0Aconst%20MyComponent%20%3D%20()%20%3D%3E%20(%0A%20%20%3CButton%20icon%3D%22camera%22%20mode%3D%22contained%22%20onPress%3D%7B()%20%3D%3E%20console.log(%27Pressed%27)%7D%3E%0A%20%20%20%20Press%20me%0A%20%20%3C%2FButton%3E%0A)%3B%0A%0Aexport%20default%20MyComponent%3B&dependencies=react-native-paper" rel="nofollow noreferrer">https://callstack.github.io/react-native-paper/button.html, and many other snack, but it always show rectangle icon.

I am using expo 36.0.0

Body:
The issue is visible in expo log as

Tried to use the icon 'stepforward' in a component from 'react-native-paper', but 'react-native-vector-icons' could not be loaded.
  To remove this warning, try installing 'react-native-vector-icons' or use another method to specify icon: https://callstack.github.io/react-native-paper/icons.html.
  Even if you try to add package it's still not resolved by this, some issue in expo as reported here Expo forums

Following is the workaround as Snack link

Using Expo vector Icon

import { Ionicons } from '@expo/vector-icons';

2.Get type

import SimpleIcon from 'react-native-vector-icons/SimpleLineIcons';

import MaterialIcons from 'react-native-vector-icons/MaterialIcons';

then pass as child


问:
MongoDB Aggregate search with comma separated string list in array
I have a MongoDB question. I have a search in an aggregation with $match.
Search should check an array if one of the values matches a value of the array inside the documents.

As an example:

```<code>var stringList = 'general,online,offline'; //--> should check each value of this list
</code>```

and two documents as an example

```<code>    {
"_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"),
"category" : [
    "general",
    "online",
    "internal",
    "miscellaneous"
]},

{
"_id" : ObjectId("5e8f3afeec717a0013d2f1fa"),
"category" : [
    "offline"
]
</code>```

}

I´ve tried a lot but I don´t found out how it is possible to check each value of the string list with each value in the category array. My example should show both documents, but if I use $in I don´t get any result.

What I tried is:

Split the list by comma and map

use of $elemMatch

use if $in

use combination of $elemMatch and $in

I hope I could explain my problem with my aggregation.

Thx everyone for his help.

答:
You should be able to split the string on , with .split function, then pass this in to a $in query.

var stringList = 'general,online,offline';

db.documents.find( { "category" : { $in : stringList.split(",") } } );
{ "_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"), "category" : [ "general", "online", "internal", "miscellaneous" ] }
{ "_id" : ObjectId("5e8f3afeec717a0013d2f1fa"), "category" : [ "offline" ] }

```

<p>You can also do this in a $match in an aggregation query.</p>

<pre class="lang-js prettyprint-override"><code>> db.documents.aggregate([
  { $match : { category: { $in : stringList.split(",") } }}
])
</code>```

Body:
I have a MongoDB question. I have a search in an aggregation with $match.
Search should check an array if one of the values matches a value of the array inside the documents.

As an example:

var stringList = 'general,online,offline'; //--> should check each value of this list

and two documents as an example

    {
"_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"),
"category" : [
    "general",
    "online",
    "internal",
    "miscellaneous"
]},

{
"_id" : ObjectId("5e8f3afeec717a0013d2f1fa"),
"category" : [
    "offline"
]

}

I´ve tried a lot but I don´t found out how it is possible to check each value of the string list with each value in the category array. My example should show both documents, but if I use $in I don´t get any result.

What I tried is:

Split the list by comma and map

use of $elemMatch

use if $in

use combination of $elemMatch and $in

I hope I could explain my problem with my aggregation.

Thx everyone for his help.

Body:
You should be able to split the string on , with .split function, then pass this in to a $in query.

var stringList = 'general,online,offline';

db.documents.find( { "category" : { $in : stringList.split(",") } } );
{ "_id" : ObjectId("5e8f3a64ec717a0013d2f1f9"), "category" : [ "general", "online", "internal", "miscellaneous" ] }
{ "_id" : ObjectId("5e8f3afeec717a0013d2f1fa"), "category" : [ "offline" ] }

You can also do this in a $match in an aggregation query.

> db.documents.aggregate([
  { $match : { category: { $in : stringList.split(",") } }}
])


问:
How to pass .property file to JAVA class from shell scripting?
How to pass .property file to JAVA class from shell scripting?
I am executing a .jar file from shell scripting. I need to pass a .property file (which is present in Server) to Java class. Please help me on this.

答:
I facing this issue and now it got solved.</p>

```<code>java -Dconfig.properties.filepath=/app1/username/application/config.properties -cp "Jarname.jar:lib/*" com.xyx.packagename.methodname
</code>```

Body:
I facing this issue and now it got solved.

java -Dconfig.properties.filepath=/app1/username/application/config.properties -cp "Jarname.jar:lib/*" com.xyx.packagename.methodname


问:
How to send mails from plsql
I am in need of sending emails to recipients from my oracle procedure, however i am restricted to use UTL_MAIL and UTL_SMTP. Other than these i am not aware of any other way of sending mails.

Also is tehre a way to connect to unix from oracle plsql code so that i can use mailx -s and trigger the mail.

Can you please help me here.

答:
UTL_MAIL and UTL_SMTP are the supported way to generate e-mail from PL/SQL and should offer a less complicated design than executing a shell script. It would also be much more secure. That said, the following links describe several different ways to execute OS scripts from within PL/SQL:

http://www.dba-oracle.com/t_execute_shell_script_plsql_procedure.htm

https://www.oracle.com/technetwork/database/enterprise-edition/calling-shell-commands-from-plsql-1-1-129519.pdf

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:9533837800346646784

https://oracle-base.com/articles/8i/shell-commands-from-plsql

Title: How to send mails from plsql


问:
Creating a local SVN branch
I am working on an SVN repository and do not want to create a new SVN branch. Instead of that, I want to create a branch local to my machine, something which could be done easily with Git.

But I am currently using SVN and need to branch out from an already-modified SVN version. In essence, I want following:

svn_repo_version = 2259

working_copy = modified 2259

new_local_svn_branch = based on modified 2259

What is the best way to go about it?

答:
I'm afraid you will have to create a new branch and keep merging any changes into it. The only alternative is to simply checkout the branch, keep updating and don't commit (or keep switching prior to commits) until you are finished. You could always have two working copies if you need to work on the original branch/trunk. Nowhere near ideal, but that's the way SVN works, which is still very good given the alternatives at the time.

I personally manage local history if that is what you are after via my IDE (Eclipse).

Title: Creating a local SVN branch


问:
how can i use Rest Sharp API put method
hey i am trying to use put method like the code below. i need have a body  like this

```<code>{
  "lines": [
    {
      "lineId": 300198921,
      "quantity": 1
    }],
  "params": {
  },
  "status": "Picking"
}
</code>```

i run the request on talend API there is no problem but in c# always getting an error

```<code>public static void TrendyolDurumGüncelle()
        {
            client = new RestClient("https://api.trendyol.com/sapigw/suppliers/{supplierId}/shipment-packages/{Id}");
            client.Authenticator = new HttpBasicAuthenticator(TrendyolUserName, TrendyolPassword);

            request = new RestRequest("https://api.trendyol.com/sapigw/suppliers/{supplierId}/shipment-packages/{Id}", Method.PUT);
            request.AddUrlSegment("supplierId", TrendyolMerchantId);
            request.AddUrlSegment("Id", "173657633");

            var body = new { lines = new {lineId = "300198921", quantity = 3 } , @params = new { } ,status = "Picking" };

            request.AddJsonBody(body);

            var response = client.Execute(request);
            var content = response.Content;

        }
</code>```

答:
In your sample json lines property is array, so try:

```<code>var body = new
{
    lines = new[] { new { lineId = "300198921", quantity = 3 } } ,
    @params = new { } ,
    status = "Picking"
};
</code>```

Title: how can i use Rest Sharp API put method

Body:
hey i am trying to use put method like the code below. i need have a body  like this

{
  "lines": [
    {
      "lineId": 300198921,
      "quantity": 1
    }],
  "params": {
  },
  "status": "Picking"
}

i run the request on talend API there is no problem but in c# always getting an error

public static void TrendyolDurumGüncelle()
        {
            client = new RestClient("https://api.trendyol.com/sapigw/suppliers/{supplierId}/shipment-packages/{Id}");
            client.Authenticator = new HttpBasicAuthenticator(TrendyolUserName, TrendyolPassword);

            request = new RestRequest("https://api.trendyol.com/sapigw/suppliers/{supplierId}/shipment-packages/{Id}", Method.PUT);
            request.AddUrlSegment("supplierId", TrendyolMerchantId);
            request.AddUrlSegment("Id", "173657633");

            var body = new { lines = new {lineId = "300198921", quantity = 3 } , @params = new { } ,status = "Picking" };

            request.AddJsonBody(body);

            var response = client.Execute(request);
            var content = response.Content;

        }

Body:
In your sample json lines property is array, so try:

var body = new
{
    lines = new[] { new { lineId = "300198921", quantity = 3 } } ,
    @params = new { } ,
    status = "Picking"
};


问:
Conditional NULL replacement
I am having a table with many columns:(previous post had just one id per one source_id, but this case has more than one id per one source_id)

```<code>id    col1             source_id
a1    765.3            a5
a2    3298.3           a4
a3    8762.1           a8
a4    3298.3           (null)
a5    (null)           a6
a6    (null)           (null)
a7    10               a5
</code>```

I want to fill null values of source _id with values from id.
For example, source_id a5 row has null which has to replaced with id a1 + id a7 values, subsequently, source_id a6 row having null to be replaced with a5 row

Output:

```<code>id    col1             source_id
a1    765.3            a5
a2    3298.3           a4
a3    8762.1           a8
a4    3298.3           (null)
a5    765.3+10=775.3   a6
a6    765.3+10=775.3   (null)
a7    10               a5
</code>```

Thanks!!

EDIT:

To make it more clear, null values in columns other than source_id and id needs to be filled. Given only col1 for simplified post, there might be many columns as well

答:
Use a correlated hierarchical query (you can correlate on either the id column or the ROWID pseudo-column):

SELECT id,
       COALESCE(
         col1,
         (
           SELECT SUM( COALESCE( col1, 0 ) )
           FROM   table_name s
           START WITH s.ROWID = t.ROWID
           CONNECT BY source_id = PRIOR id
         )
       ) AS col1,
       source_id
FROM   table_name t;
```

<p>So, for your sample data:</p>

<pre class="lang-sql prettyprint-override"><code>CREATE TABLE table_name ( id, col1, source_id ) AS
SELECT 'a1',  765.3, 'a5' FROM DUAL UNION ALL
SELECT 'a2', 3298.3, 'a4' FROM DUAL UNION ALL
SELECT 'a3', 8762.1, 'a8' FROM DUAL UNION ALL
SELECT 'a4', 3298.3, null FROM DUAL UNION ALL
SELECT 'a5',   null, 'a6' FROM DUAL UNION ALL
SELECT 'a6',   null, null FROM DUAL UNION ALL
SELECT 'a7',     10, 'a5' FROM DUAL;
</code>```

This outputs:

```
ID |   COL1 | SOURCE_ID
:- | -----: | :--------
a1 |  765.3 | a5
a2 | 3298.3 | a4
a3 | 8762.1 | a8
a4 | 3298.3 | <em>null</em>
a5 |  775.3 | a6
a6 |  775.3 | <em>null</em>
a7 |     10 | a5
```

You might need to stop iterating through the when you find the first non-null value in each branch of the hierarchy. That would just require adding a simple filter:

SELECT id,
       COALESCE(
         col1,
         (
           SELECT SUM( COALESCE( col1, 0 ) )
           FROM   table_name s
           START WITH s.ROWID = t.ROWID
           CONNECT BY source_id = PRIOR id
                  AND PRIOR col1 IS NULL
         )
       ) AS col1,
       source_id
FROM   table_name t;
```

(The output is the same as above).

db<>fiddle here

Title: Conditional NULL replacement

Body:
I am having a table with many columns:(previous post had just one id per one source_id, but this case has more than one id per one source_id)

id    col1             source_id
a1    765.3            a5
a2    3298.3           a4
a3    8762.1           a8
a4    3298.3           (null)
a5    (null)           a6
a6    (null)           (null)
a7    10               a5

I want to fill null values of source _id with values from id.
For example, source_id a5 row has null which has to replaced with id a1 + id a7 values, subsequently, source_id a6 row having null to be replaced with a5 row

Output:

id    col1             source_id
a1    765.3            a5
a2    3298.3           a4
a3    8762.1           a8
a4    3298.3           (null)
a5    765.3+10=775.3   a6
a6    765.3+10=775.3   (null)
a7    10               a5

Thanks!!

EDIT:

To make it more clear, null values in columns other than source_id and id needs to be filled. Given only col1 for simplified post, there might be many columns as well

Body:
Use a correlated hierarchical query (you can correlate on either the id column or the ROWID pseudo-column):

SELECT id,
       COALESCE(
         col1,
         (
           SELECT SUM( COALESCE( col1, 0 ) )
           FROM   table_name s
           START WITH s.ROWID = t.ROWID
           CONNECT BY source_id = PRIOR id
         )
       ) AS col1,
       source_id
FROM   table_name t;

So, for your sample data:

CREATE TABLE table_name ( id, col1, source_id ) AS
SELECT 'a1',  765.3, 'a5' FROM DUAL UNION ALL
SELECT 'a2', 3298.3, 'a4' FROM DUAL UNION ALL
SELECT 'a3', 8762.1, 'a8' FROM DUAL UNION ALL
SELECT 'a4', 3298.3, null FROM DUAL UNION ALL
SELECT 'a5',   null, 'a6' FROM DUAL UNION ALL
SELECT 'a6',   null, null FROM DUAL UNION ALL
SELECT 'a7',     10, 'a5' FROM DUAL;

This outputs:

ID |   COL1 | SOURCE_ID
:- | -----: | :--------
a1 |  765.3 | a5
a2 | 3298.3 | a4
a3 | 8762.1 | a8
a4 | 3298.3 | null
a5 |  775.3 | a6
a6 |  775.3 | null
a7 |     10 | a5

You might need to stop iterating through the when you find the first non-null value in each branch of the hierarchy. That would just require adding a simple filter:

SELECT id,
       COALESCE(
         col1,
         (
           SELECT SUM( COALESCE( col1, 0 ) )
           FROM   table_name s
           START WITH s.ROWID = t.ROWID
           CONNECT BY source_id = PRIOR id
                  AND PRIOR col1 IS NULL
         )
       ) AS col1,
       source_id
FROM   table_name t;

(The output is the same as above).

db<>fiddle here


问:
How can I use PHP values in .js Extension Files?
```<code>var Facilites = {
    "91": {
        "facilites": "Wifi:Fans:AC",
        "RoomcatgId": "91"
    },
    "95": {
        "RoomcatgId": "95",
        "facilites": "Air Cooler:Daily Newspaper:Wifi:Fans"
    }
}
</code>```

In Above code I want to Add PHP Wordpress Code in facilities field, But How Can I put PHP Codes in .js Extension Files?

```<code><?php
$facilities = get_field_object('facilities');
value = $facilities['value'];
echo "<span>";
    if( $value ):
        foreach( $value as $val ):
            $fac = implode( ":", $facilities['choices'][ $val ] );
                echo $fac;
        endforeach;
    endif;
echo "</span>";
?>
</code>```

in the field facilities I want to add above PHP code like:

```<code>"91": { "facilities": "<?php #php code here ?>" }
</code>```

答:
The result depends on how your code/files work together but it is possible. You don't need to add PHP code to your .js file. That file can't process PHP code. Unless the javascript code is in the .php file as well.

Try this (I just copied your code, didn't check it):

```<code><?php
$facilities = get_field_object('facilities');
value = $facilities['value'];
$myJSValues = "";
    if( $value ):
        foreach( $value as $val ):
            $fac = implode( ":", $facilities['choices'][ $val ] );
                $myJSValues .= $fac;
        endforeach;
    endif;
?>
<script>
var myValues = <?php echo $myJSValues; ?>
</script>
</code>```

in your .js file use myValues

Body:
var Facilites = {
    "91": {
        "facilites": "Wifi:Fans:AC",
        "RoomcatgId": "91"
    },
    "95": {
        "RoomcatgId": "95",
        "facilites": "Air Cooler:Daily Newspaper:Wifi:Fans"
    }
}

In Above code I want to Add PHP Wordpress Code in facilities field, But How Can I put PHP Codes in .js Extension Files?

<?php
$facilities = get_field_object('facilities');
value = $facilities['value'];
echo "";
    if( $value ):
        foreach( $value as $val ):
            $fac = implode( ":", $facilities['choices'][ $val ] );
                echo $fac;
        endforeach;
    endif;
echo "";
?>

in the field facilities I want to add above PHP code like:

"91": { "facilities": "<?php #php code here ?>" }

Body:
The result depends on how your code/files work together but it is possible. You don't need to add PHP code to your .js file. That file can't process PHP code. Unless the javascript code is in the .php file as well.

Try this (I just copied your code, didn't check it):

<?php
$facilities = get_field_object('facilities');
value = $facilities['value'];
$myJSValues = "";
    if( $value ):
        foreach( $value as $val ):
            $fac = implode( ":", $facilities['choices'][ $val ] );
                $myJSValues .= $fac;
        endforeach;
    endif;
?>
<script>
var myValues = <?php echo $myJSValues; ?>
</script>

in your .js file use myValues


问:
Integrate Robot Framework with Zephyr for jira
I would like to know if there is the option of integrating automated test cases with zephyr de jira.

Currently, I have a battery of automated tests in robot framework. In parallel, I have the test cases defined in Zephyr for jira. I would like to be able to launch the execution of the automated test cases from Zephyr or else, that the result of the executions will be reflected in the Zephyr test cases.

Thank you.

答:
You need to parse output.xml file generated by Robot Framework to get results of your test suite. Alternatively JUnit xml reporting file may be generated by using -x parameter:

```<code>robot -x junit.xml test1.robot
</code>```

To update results in Zephyr test cases use ZAPI for Jira. Please check https://getzephyr.docs.apiary.io.

Execution status update

Find test case id (issue id) by test case name (issue key):

```<code>https://<jira_server>/rest/api/2/issue/<test_case_name>
</code>```

Find execution id by test case id:

```<code>https://<jira_server>/rest/zapi/latest/execution?issueId=<test_case_id>
</code>```

Request:

```<code>PUT https://<jira_server>/rest/zapi/latest/execution/<execution_id>/execute
</code>```

Headers:

```<code>Content-Type: application/json
</code>```

Body:

```<code>{
  "status": "1"
}
</code>```

Status "1" is for PASS.

Step status update

Find step id by execution id:

```<code>https://<jira_server>/rest/zapi/latest/stepResult?executionId=<execution_id>&expand=
</code>```

Request:

```<code>PUT https://<jira_server>/rest/zapi/latest/stepResult/<step_id>
</code>```

Headers and body the same as above.

Body:
You need to parse output.xml file generated by Robot Framework to get results of your test suite. Alternatively JUnit xml reporting file may be generated by using -x parameter:

robot -x junit.xml test1.robot

To update results in Zephyr test cases use ZAPI for Jira. Please check https://getzephyr.docs.apiary.io.

Execution status update

Find test case id (issue id) by test case name (issue key):

https://<jira_server>/rest/api/2/issue/<test_case_name>

Find execution id by test case id:

https://<jira_server>/rest/zapi/latest/execution?issueId=<test_case_id>

Request:

PUT https://<jira_server>/rest/zapi/latest/execution/<execution_id>/execute

Headers:

Content-Type: application/json

Body:

{
  "status": "1"
}

Status "1" is for PASS.

Step status update

Find step id by execution id:

https://<jira_server>/rest/zapi/latest/stepResult?executionId=<execution_id>&expand=

Request:

PUT https://<jira_server>/rest/zapi/latest/stepResult/<step_id>

Headers and body the same as above.


问:
Callback functions that depend on one another in Android Studio - a more elegant solution
I have 2 callback functions in my app, one of which requires the other one's result, so I want them to execute asynchronously. The scenario is this:

I obtain the device's token with FirebaseInstanceId.getInstance().getInstanceId(). That's the 1st callback.

When I have the token, I use it in accessing the Firebase Realtime DB to get the user's data. That's the 2nd callback.

In my current solution, I'm using AsyncTask with a Semaphore in the doInBackground function, like so:

```<code>private class AsyncOp extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... voids) {
            final Semaphore semaphore = new Semaphore(0);
            FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
                @Override
                public void onSuccess(InstanceIdResult instanceIdResult) {
                    token = instanceIdResult.getToken();
                    JSONObject requestObject = new JSONObject();
                    try {
                        requestObject.put("token", token);
                        semaphore.release();
                    } catch (JSONException e) {
                        Log.e(TAG_MAINACTIVITY, token);
                        semaphore.release();
                    }
                    JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
                            requestObject, new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            Log.i(TAG_MAINACTIVITY, "Token saved successfully");
                        }
                    },
                            new Response.ErrorListener() {
                                @Override
                                public void onErrorResponse(VolleyError error) {
                                    Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
                                }
                            });

                    _queue.add(req);
                }
            });

            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return token;
        }

        @Override
        protected void onPostExecute(String token) {
            getUser(token);
        }
    }

 public void getUser(String token) {
        db.child("users").child(token).addListenerForSingleValueEvent(new ValueEventListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if (!dataSnapshot.exists()) {
                    // Navigate to fragment where new users can sign up:
                    goToSignup();
                } else {
                    currentUser = dataSnapshot.getValue(User.class);
                    assert currentUser != null;
                    updateHeadline(currentUser.getName()); // Update UI to display the user's name
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                Log.d(TAG_MAINACTIVITY, databaseError.getMessage());
            }
        });
    }
</code>```

and in my OnCreate I execute as follows:

```<code>_queue = Volley.newRequestQueue(this);
AsyncOp getToken = new AsyncOp();
getToken.execute();
</code>```

It works just fine, but I can't help but feel like I'm missing the whole point here and that there's a better solution that I can use. I've scoured other StackOverflow questions dealing with similar issues and found some suggestions, but I got tangled up trying to implement them, being pretty new to this whole ordeal (that's actually my first "real" project). I tried looking for something that would work like a Promise and found Future but I probably didn't do it properly since it didn't work. That's the only solution that worked for me, other than simply nesting getUser(token) inside the first callback. So if you have any ideas that would work for me, I'd be glad to hear it.

答:
Firebase performs all network and disk I/O off the main thread. That means there is seldom a reason to run Firebase interactions in a background task.

Aside from that, the flow is significantly more complicated when you use a semaphore. I'd consider just putting the call to get a user into the completion handler of the previous call.

Combined that becomes:

```<code>FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
    @Override
    public void onSuccess(InstanceIdResult instanceIdResult) {
        token = instanceIdResult.getToken();
        JSONObject requestObject = new JSONObject();
        requestObject.put("token", token);

        JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
                requestObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                Log.i(TAG_MAINACTIVITY, "Token saved successfully");
                getUser(token);
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
            }
        });
        _queue.add(req);
    }
});
</code>```

Body:
I have 2 callback functions in my app, one of which requires the other one's result, so I want them to execute asynchronously. The scenario is this:

I obtain the device's token with FirebaseInstanceId.getInstance().getInstanceId(). That's the 1st callback.

When I have the token, I use it in accessing the Firebase Realtime DB to get the user's data. That's the 2nd callback.

In my current solution, I'm using AsyncTask with a Semaphore in the doInBackground function, like so:

private class AsyncOp extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... voids) {
            final Semaphore semaphore = new Semaphore(0);
            FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
                @Override
                public void onSuccess(InstanceIdResult instanceIdResult) {
                    token = instanceIdResult.getToken();
                    JSONObject requestObject = new JSONObject();
                    try {
                        requestObject.put("token", token);
                        semaphore.release();
                    } catch (JSONException e) {
                        Log.e(TAG_MAINACTIVITY, token);
                        semaphore.release();
                    }
                    JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
                            requestObject, new Response.Listener<JSONObject>() {
                        @Override
                        public void onResponse(JSONObject response) {
                            Log.i(TAG_MAINACTIVITY, "Token saved successfully");
                        }
                    },
                            new Response.ErrorListener() {
                                @Override
                                public void onErrorResponse(VolleyError error) {
                                    Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
                                }
                            });

                    _queue.add(req);
                }
            });

            try {
                semaphore.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return token;
        }

        @Override
        protected void onPostExecute(String token) {
            getUser(token);
        }
    }

 public void getUser(String token) {
        db.child("users").child(token).addListenerForSingleValueEvent(new ValueEventListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                if (!dataSnapshot.exists()) {
                    // Navigate to fragment where new users can sign up:
                    goToSignup();
                } else {
                    currentUser = dataSnapshot.getValue(User.class);
                    assert currentUser != null;
                    updateHeadline(currentUser.getName()); // Update UI to display the user's name
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                Log.d(TAG_MAINACTIVITY, databaseError.getMessage());
            }
        });
    }

and in my OnCreate I execute as follows:

_queue = Volley.newRequestQueue(this);
AsyncOp getToken = new AsyncOp();
getToken.execute();

It works just fine, but I can't help but feel like I'm missing the whole point here and that there's a better solution that I can use. I've scoured other StackOverflow questions dealing with similar issues and found some suggestions, but I got tangled up trying to implement them, being pretty new to this whole ordeal (that's actually my first "real" project). I tried looking for something that would work like a Promise and found Future but I probably didn't do it properly since it didn't work. That's the only solution that worked for me, other than simply nesting getUser(token) inside the first callback. So if you have any ideas that would work for me, I'd be glad to hear it.

Body:
Firebase performs all network and disk I/O off the main thread. That means there is seldom a reason to run Firebase interactions in a background task.

Aside from that, the flow is significantly more complicated when you use a semaphore. I'd consider just putting the call to get a user into the completion handler of the previous call.

Combined that becomes:

FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
    @Override
    public void onSuccess(InstanceIdResult instanceIdResult) {
        token = instanceIdResult.getToken();
        JSONObject requestObject = new JSONObject();
        requestObject.put("token", token);

        JsonObjectRequest req = new JsonObjectRequest(Request.Method.POST, REQUEST_URL + "token",
                requestObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                Log.i(TAG_MAINACTIVITY, "Token saved successfully");
                getUser(token);
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG_MAINACTIVITY, "Failed to save token - " + error);
            }
        });
        _queue.add(req);
    }
});


问:
In my compiled Livecode desktop app, the PC version saves files and folders as expected. The Mac compiled version is all wrong
In my desktop app, I have a very defined file and folder structure:

main_folder ---folder2 ------file1 ------file2 ---folder3 ------file1 ------file2 etc...

On PC, this writes fine.  I define the main folder and sub folders:

put "c:\folder1\folder2\file1" into someVariable

On Mac, I have:

put specialfolderpath("Documents") & "/folder1/folder2/file1" into someVariable

On PC, it writes the files to the folders as expected.  On the Mac, it seems to write a folder/file combo:

/folder1/folder2/file1

as a file.

For the software to work, I copy the folder/file structure to the Mac as it is on the PC.

The Mac app is not finding the existing files and is then writing new files underneath the existing folders/files as new files.

It's all very confusing and I just don't understand why it's not working as it should.

答:
LiveCode will create a new file if it cannot find an existing one.

I don't think you can concatenate folders when using "specialFolderPath". Check out the dictionary, which only gives examples where a single folder is included.

Try this:

```<code>answer folder "Select Folder"
put it into folderPath
</code>```

Check out what comes back in the local variable "it". Then test that.

Body:
LiveCode will create a new file if it cannot find an existing one.

I don't think you can concatenate folders when using "specialFolderPath". Check out the dictionary, which only gives examples where a single folder is included.

Try this:

answer folder "Select Folder"
put it into folderPath

Check out what comes back in the local variable "it". Then test that.