I keep getting this error for my code.

I would like to send a notification using Firebase Cloud Messaging to a single device. I already got the FCM token of the device, but how to set the notification to the device.

How to change the API? and the topic, how to find them?

E/SpannableStringBuilder: SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero-length.

E/Volley: [1130] BasicNetwork.performRequest: Unexpected response code 401 for https://fcm.googleapis.com/fcm/send

I will provide the code, please help:

MainActivity.java

public class MainActivity extends AppCompatActivity {
    EditText edtTitle;
    EditText edtMessage;
    final private String FCM_API = "https://fcm.googleapis.com/fcm/send";
    final private String serverKey = "key=" + "Your server key";
    final private String contentType = "application/json";
    final String TAG = "NOTIFICATION TAG";

    String NOTIFICATION_TITLE;
    String NOTIFICATION_MESSAGE;
    String TOPIC;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_emergency);
        edtTitle = findViewById(R.id.edtTitle);
        edtMessage = findViewById(R.id.edtMessage);

        findViewById(R.id.btnSend).setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                TOPIC = "/topics/userABC"; //topic has to match what the receiver subscribed to
                NOTIFICATION_TITLE = edtTitle.getText().toString();
                NOTIFICATION_MESSAGE = edtMessage.getText().toString();

                JSONObject notification = new JSONObject();
                JSONObject notifcationBody = new JSONObject();
                try {
                    notifcationBody.put("title", NOTIFICATION_TITLE);
                    notifcationBody.put("message", NOTIFICATION_MESSAGE);

                    notification.put("to", TOPIC);
                    notification.put("data", notifcationBody);
                } catch (JSONException e) {
                    Log.e(TAG, "onCreate: " + e.getMessage() );
                }
                sendNotification(notification);
            }
        });

    }

    private void sendNotification(JSONObject notification) {
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(FCM_API, notification,
                new Response.Listener<JSONObject>() {
                    @Override
                    public void onResponse(JSONObject response) {
                        Log.i(TAG, "onResponse: " + response.toString());
                        edtTitle.setText("");
                        edtMessage.setText("");
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        Toast.makeText(Emergency.this, "Request error", Toast.LENGTH_LONG).show();
                        Log.i(TAG, "onErrorResponse: Didn't work");
                    }
                }){
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> params = new HashMap<>();
                params.put("Authorization", serverKey);
                params.put("Content-Type", contentType);
                return params;
            }
        };
        MySingleton.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest);
    }
}

MyFirebaseInstanceId.java

public class MyFirebaseInstanceIDService extends FirebaseInstanceIdService {

    private static final String TAG = "mFirebaseIIDService";
    private static final String SUBSCRIBE_TO = "userABC";

    @Override
    public void onTokenRefresh() {
        /*
          This method is invoked whenever the token refreshes
          OPTIONAL: If you want to send messages to this application instance
          or manage this apps subscriptions on the server side,
          you can send this token to your server.
        */
        String token = FirebaseInstanceId.getInstance().getToken();

        // Once the token is generated, subscribe to topic with the userId
        FirebaseMessaging.getInstance().subscribeToTopic(SUBSCRIBE_TO);
        Log.i(TAG, "onTokenRefresh completed with token: " + token);
    }
}

MySingleton.java

public class MySingleton {
    private  static MySingleton instance;
    private RequestQueue requestQueue;
    private Context ctx;

    private MySingleton(Context context) {
        ctx = context;
        requestQueue = getRequestQueue();
    }

    public static synchronized MySingleton getInstance(Context context) {
        if (instance == null) {
            instance = new MySingleton(context);
        }
        return instance;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            // getApplicationContext() is key, it keeps you from leaking the
            // Activity or BroadcastReceiver if someone passes one in.
            requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
        }
        return requestQueue;
    }

    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }
}

MyFirebaseMessagingService

public class MyFirebaseMessagingService extends FirebaseMessagingService {

    private final String ADMIN_CHANNEL_ID ="admin_channel";

    @Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        final Intent intent = new Intent(this, Emergency.class);
        NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
        int notificationID = new Random().nextInt(3000);

      /*
        Apps targeting SDK 26 or above (Android O) must implement notification channels and add its notifications
        to at least one of them. Therefore, confirm if version is Oreo or higher, then setup notification channel
      */
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            setupChannels(notificationManager);
        }

        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this , 0, intent,
                PendingIntent.FLAG_ONE_SHOT);

        Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),
                R.drawable.notify_icon);

        Uri notificationSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, ADMIN_CHANNEL_ID)
                .setSmallIcon(R.drawable.notify_icon)
                .setLargeIcon(largeIcon)
                .setContentTitle(remoteMessage.getData().get("title"))
                .setContentText(remoteMessage.getData().get("message"))
                .setAutoCancel(true)
                .setSound(notificationSoundUri)
                .setContentIntent(pendingIntent);

        //Set notification color to match your app color template
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
            notificationBuilder.setColor(getResources().getColor(R.color.colorPrimaryDark));
        }
        notificationManager.notify(notificationID, notificationBuilder.build());
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private void setupChannels(NotificationManager notificationManager){
        CharSequence adminChannelName = "New notification";
        String adminChannelDescription = "Device to devie notification";

        NotificationChannel adminChannel;
        adminChannel = new NotificationChannel(ADMIN_CHANNEL_ID, adminChannelName, NotificationManager.IMPORTANCE_HIGH);
        adminChannel.setDescription(adminChannelDescription);
        adminChannel.enableLights(true);
        adminChannel.setLightColor(Color.RED);
        adminChannel.enableVibration(true);
        if (notificationManager != null) {
            notificationManager.createNotificationChannel(adminChannel);
        }
    }
}

I need to show camera preview in live wallpaper. I've already made for android < M versions. But can't understand how it working with new API. Oldest Camera is deprecated now

In google example they put it in xml and in TextureView but how I can change that for my needs, I can't understand.

I'm new to Stack Overflow. Please excuse me if this question seems a bit amateur. I only have a few months Android programming experience.

I need to connect an ESP8266 softAP to my Android App in code, exchange some data for a pairing procedure and then connect to an external wifi network. I have a pairing procedure similar to the one used between Sonoff devices and eWeLink, in mind.

I get the app connected to the ESP8266 softAP successfully, but there is no communication between the devices. After spending some time with it, I noticed when I connect to the softAP manually, I get a prompt from android to stay connected to the network that doesn't have an Internet connection. When I click on yes, all is good and I can communicate. But, I cant expect the user to go through this process to pair a device with the network.

So my question is, is there a way to override this prompt, force android to accept the network without an internet connection and start communicating?

For android test projects management issue, I need to use some older versions of android plugins, such as compileSdkVersion, com.android.tools.build:gradle:3.0.1, gradle-4.5.1-all.zip.

Android studio will always trend to apply the latest available plugins when I try to create a new project.
This will lead to a serious issue: every time I create a new project, I have to manually downgrade a lot of plugin versions, remove a lot of new features which only exist in some newer API versions.

Need to update a lot of codes, for example:

compileSdkVersion 23
distributionUrl=https\://services.gradle.org/distributions/gradle-4.5.1-all.zip
classpath 'com.android.tools.build:gradle:3.0.1'
android:roundIcon="@mipmap/ic_launcher_round"

I wish to find a default version settings for these plugins, but could not find such method.
Could any one help? Thanks in advance!

When I try to run the app in emulator it gives the error but does not show what the error is like null pointer or any so ever error it is. I am really facing huge problem to identify what the error detail is. I would highly appreciate if anybody helps me to fix this in my logcat.

I want to scroll my Spinner to specific position when user clicks on it. There are more than 50 items in it. That means I want to add initial position to almost top of the dropdown menu.

Tried this, doesnt work.

spinner?.setOnTouchListener { v, event ->
            v.scrollTo(v.scrollX, 0)
            v.performClick()
        }

Please have a look at the attachment When user clicks on item in a row, cross image changes into confirm icon image It is attendance app so as selected row has different image than unselected row

This image shows my point:

enter image description here

I want to create a text editor like below, but I don't know where to start, so I hope everyone can guide me to any library to complete it. Thanks everyone!

!https://www.upsieutoc.com/images/2019/08/20/Screenshot_20190819-213315.png

I am making a Sweet order like App, I want to sort Orders according to order status like Placed(0), Shipped(1), OnTheWay(2), Delivered(3). If order status is 3(Delivered) I need to show that order at the bottom of the recyclerview, Currently I am using Stack Format to view orders, is it possible?

private void loadOrders(final String phone) {

        adapter = new FirebaseRecyclerAdapter<Request, OrderViewHolder>(
                Request.class,
                R.layout.order_layout,
                OrderViewHolder.class,
                requests.orderByChild("phone").equalTo(phone)
        ) {
            @Override
            protected void populateViewHolder(OrderViewHolder orderViewHolder, final Request request, final int i) {

                final String OrderId, OrderPhone, OrderTotal, OrderAddress, OrderComment, OrderUserName, OrderTime, OrderDate;

                OrderId = adapter.getRef(i).getKey();
                OrderPhone = request.getPhone();
                OrderStatus = Common.convertCodeToStatus(request.getStatus());
                OrderTotal = request.getTotal();
                OrderAddress = request.getAddress();
                OrderComment = request.getComment();
                OrderUserName = request.getName();
                OrderTime = request.getTime();
                OrderDate = request.getDate();

                if (request.getStatus().equals("3")){

                    orderViewHolder.orderStatusImage.setImageResource(R.mipmap.cupcake);
                    orderViewHolder.orderStatusImage.setScaleType(ImageView.ScaleType.CENTER_CROP);

                    orderViewHolder.txtOrderStatus.setVisibility(View.GONE);
                    orderViewHolder.txtOrderDate.setVisibility(View.GONE);
                    orderViewHolder.txtOrderTime.setVisibility(View.GONE);

                    orderViewHolder.deliveredStatus.setVisibility(View.VISIBLE);

                }

                orderViewHolder.txtOrderId.setText(String.format("Order Id :  %s",OrderId));
                orderViewHolder.txtOrderStatus.setText(String.format("Order Status :  %s",OrderStatus));
                orderViewHolder.txtOrderTime.setText(String.format("Order Time : %s",OrderTime));
                orderViewHolder.txtOrderDate.setText(String.format("Order Date : %s",OrderDate));

                if (dialog.isShowing()){
                    dialog.dismiss();
                }

                //Prevention for app crash when user clicks
                orderViewHolder.setItemClickListener(new ItemClickListener() {
                    @Override
                    public void onClick(View view, int position, boolean isLongClick) {
                        Intent orderDetail = new Intent(getActivity(), OrderDetail.class);
                        orderDetail.putExtra("OrderId",OrderId)
                                .putExtra("OrderPhone",phone)
                                .putExtra("OrderTotal",OrderTotal)
                                .putExtra("OrderAddress",OrderAddress)
                                .putExtra("OrderComment",OrderComment)
                                .putExtra("OrderUserName",OrderUserName)
                                .putExtra("OrderTime",OrderTime)
                                .putExtra("OrderDate",OrderDate)
                                .putExtra("OrderStatus",request.getStatus());

                        startActivity(orderDetail);
                    }
                });

            }
        };
        adapter.notifyDataSetChanged();
        recyclerView.setAdapter(adapter);
    }

I implemented a CarrierMessagingService like that:

public class MyService extends CarrierMessagingService {

    public void onReceiveTextSms(@NonNull MessagePdu pdu, @NonNull String format,
                                 int destPort, int subId, @NonNull final ResultCallback<Integer> callback) {
        Log.i("MyService","onReceiveSms");
    }
}

With this manifest:

<application
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".MyService"
            android:permission="android.permission.BIND_CARRIER_SERVICES">
            <intent-filter>
                <action android:name="android.service.carrier.CarrierMessagingService" />
            </intent-filter>
        </service>
    </application>

Then I sent myself a sms. I expected to reach the log that i put in the method onReceiveTextSms of the CarrierMessagingService...However I did not reach it. Why is that?

I have create a application when I use debugging mode, the application works correctly but it dose not work in release mode!!! and don't show me any message that help me

java.lang.IllegalArgumentException: Unable to locate adb
    at com.android.tools.idea.run.editor.DeployTargetPickerDialog.<init>(DeployTargetPickerDialog.java:144)
    at com.android.tools.idea.run.editor.ShowChooserTargetProvider.showPrompt(ShowChooserTargetProvider.java:113)
    at com.android.tools.idea.run.AndroidRunConfigurationBase.getDeployTarget(AndroidRunConfigurationBase.java:600)
    at com.android.tools.idea.run.AndroidRunConfigurationBase.doGetState(AndroidRunConfigurationBase.java:281)
    at com.android.tools.idea.run.AndroidRunConfigurationBase.getState(AndroidRunConfigurationBase.java:241)
    at com.intellij.execution.runners.ExecutionEnvironment.getState(ExecutionEnvironment.java:158)
    at com.intellij.execution.runners.BaseProgramRunner.execute(BaseProgramRunner.java:55)
    at com.intellij.execution.runners.BaseProgramRunner.execute(BaseProgramRunner.java:50)
    at com.intellij.execution.ProgramRunnerUtil.executeConfigurationAsync(ProgramRunnerUtil.java:92)
    at com.intellij.execution.ProgramRunnerUtil.executeConfiguration(ProgramRunnerUtil.java:41)
    at com.intellij.execution.impl.ExecutionManagerImpl.restart(ExecutionManagerImpl.java:93)
    at com.intellij.execution.impl.ExecutionManagerImpl.access$300(ExecutionManagerImpl.java:44)
    at com.intellij.execution.impl.ExecutionManagerImpl$3.run(ExecutionManagerImpl.java:442)
    at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:232)
    at com.intellij.util.Alarm$Request.runSafely(Alarm.java:356)
    at com.intellij.util.Alarm$Request.run(Alarm.java:343)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at com.intellij.util.concurrency.SchedulingWrapper$MyScheduledFutureTask.run(SchedulingWrapper.java:228)
    at com.intellij.openapi.application.TransactionGuardImpl$2.run(TransactionGuardImpl.java:315)
    at com.intellij.openapi.application.impl.LaterInvocator$FlushQueue.doRun(LaterInvocator.java:435)
    at com.intellij.openapi.application.impl.LaterInvocator$FlushQueue.runNextEvent(LaterInvocator.java:419)
    at com.intellij.openapi.application.impl.LaterInvocator$FlushQueue.run(LaterInvocator.java:403)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:311)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:762)
    at java.awt.EventQueue.access$500(EventQueue.java:98)
    at java.awt.EventQueue$3.run(EventQueue.java:715)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:732)
    at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.java:755)
    at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:704)
    at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:391)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

I use some automation tool like uiautomator2 to control 3'rd party applications. I switch to developer mode, but I don't want the application "bot detection" to know I control it from remote. I found ADB_ENABLE flag is ON, right ? https://developer.android.com/reference/android/provider/Settings.Global.html#ADB_ENABLED

Can I mask it somehow ?

In my app I have 2 spinners they are populated with JSON data pulled from a file on my company server. The spinners are populated if a correct email, password and clientID is entered. Now I want to add that if the details are wrong or non exist they must show a different JSON.

I am trying to do this by calling an else if statement in my onResponse method.

To summarize I want each spinner to show a JSON data array with categories/client details in if the login information is entered/correct (this works but I was asked to add this second array for errors) and if there is missing/incorrect information it must show the the JSON array with the errors in. Both JSON arrays are in the same file.

I believe my problem lies with my adapter, as it is calling one ArrayList is it possible to let it call both array lists heres the adapter, I want to add a second ArrayList to this, the current one is "CategoryName"

  spinner.setAdapter(new ArrayAdapter<>(SecondActivity.this, android.R.layout.simple_spinner_dropdown_item, CategoryName));

CODE FOR LOADING THE SPINNERS DATA

private void loadSpinnerData(String url) {

    RequestQueue requestQueue=Volley.newRequestQueue(getApplicationContext());
    StringRequest stringRequest=new StringRequest(Request.Method.GET, url, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {


            try {
                JSONObject jsonObject=new JSONObject(response);

                if (jsonObject.getInt("success") == 1) {

                    JSONArray jsonArray=jsonObject.getJSONArray("Name");
                    for (int i=0; i < jsonArray.length(); i++) {
                        JSONObject jsonObject1=jsonArray.getJSONObject(i);

                        String category=jsonObject1.getString("Category");
                        CategoryName.add(category);
                    }
                }
                if (jsonObject.getInt("failed") == 1) {
                    JSONArray jsonArray=jsonObject.getJSONArray("errors");
                    for (int i=0; i < jsonArray.length(); i++) {
                        JSONObject jsonObject1=jsonArray.getJSONObject(i);

                        String error=jsonObject1.getString("reason");
                        Errors.add(error);


                    }
                }
                spinner.setAdapter(new ArrayAdapter<>(SecondActivity.this, android.R.layout.simple_spinner_dropdown_item, CategoryName));


            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {

            error.printStackTrace();
        }
    });
    int socketTimeout=30000;
    RetryPolicy policy=new DefaultRetryPolicy(socketTimeout, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    stringRequest.setRetryPolicy(policy);

    requestQueue.add(stringRequest);

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.example.livedataapp.User.getName()' on a null object reference

private void loadUser(User user) {

    editTextName.setText(user.getName());
    editTextDescription.setText(user.getDescription());
    editTextDriver.setText(user.getDriver());
}

I get the list of elements from the HTTP response, then I want to dynamically insert that list into the textview inside the "box" that you can see, currently it just inserts a string and overlaps them one over the other. I tried changing the layout (all three constraint, relative and linear) and it didn't help. Does anyone know how to position them dynamicly inside the boxes and not overlap but have margins like in the second picture? Otherwise, inside the project, I use a constrain layout.

Here is my code:

RelativeLayout parentLayout = (RelativeLayout) findViewById(R.id.layout);

                    int size = response.toArray().length;

                    final TextView[] tv = new TextView[size];
                    TextView temp;

                    for (int i = 0; i < size; i++)
                    {
                        temp = new TextView(Activity.this);

                        temp.setText(response.get(i).getName());

                        parentLayout.addView(temp);

                        tv[i] = temp;

                    }

Here is the picture how it looks right now:

enter image description here

And here is the picture how I want it to looks like:

enter image description here

I am trying to set different colors for Title and Burger Menu Icon. But no matter what combination I try, they always show up in same color.

This is what I am trying to achive :

enter image description here

colors.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="launcher_background">#FFFFFF</color>
    <color name="colorPrimary">#FFFFFF</color>
    <color name="colorPrimaryDark">#03213F</color>
    <color name="colorAccent">#63B34A</color>
</resources>

styles.xml :

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <style name="MainTheme" parent="MainTheme.Base">
  </style>
  <style name="MainTheme.Base" parent="Theme.AppCompat.Light">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="windowActionModeOverlay">true</item>
    <item name="android:datePickerDialogTheme">@style/AppCompatDialogStyle</item>

  </style>
  <style name="AppCompatDialogStyle" parent="Theme.AppCompat.Light.Dialog">
    <item name="colorAccent">#63B34A</item>
  </style>
  <style name="ToolbarTheme" parent="ThemeOverlay.AppCompat.ActionBar">
    <item name="android:fontFamily">@font/avenir</item>
  </style>
</resources>

Toolbar.axml :

<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/colorPrimary"
    android:theme="@style/ToolbarTheme"
    android:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

One of my young colleague is override the official class name. I had learnt from the past that I should not use that way since it will create difficult bug to spot. Since it is located in the header.

For example

from django.db import models


class Model(models.Model):
    class Meta:
        abstract = True

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

I had asked him to rename this from Model to AbstractModel to be more precise, but his answer is No.

He is not going to rename it because he knows from the header. It comes to this point because his IDE is not fully support auto-import. Therefore he has to memorize all the directory structure entire project, but I had recommend that get access to classname fast from IDE is the productive way and you will be able to see content without scroll up to the header. He rejected my solution.

Questions
1. Am I wrong?
2. Should I relocate him out from my project soon?

Can a Data Access Object (DAO) send HTTP requests or is it only supposed to communicate with data persistence APIs ?

I am working on a microservice architecture using CQS and with domain objects built using DDD aggregates. I am just beginning to learn about CQS, CQRS, Domain Driven Design, so excuse me if what I post is completely wrong from either perspective. Currently, the architecture within a microservice is as follows:

Write side: RestApi situated at the controller level deserializes json bodies to commands (Controller layer) => (Service layer) commands are handled in command handlers where business logic is invoked on the aggregates, or handled within the handler itself => (Repository layer) domain objects are saved into (and hydrated from) the database via a Write repository (Database is shared between read and write layer, so there is no separate DB for projections as in CQRS)

Read side: Rest api (Controller layer) => communicates directly with read repositories which return DTOs. Have introduced also query handlers for aggregating data from multiple repositories (and services), when this is necessary.

Also, the aggregates are attempting to follow concepts described in Vaughn Vernon's Efficient aggregate design, whereas if an aggregate root needs to hold a reference to a different aggregate root, it does so by only storing the id and not the whole aggregate.

For the purpose of this questions, I will introduce a basic aggregate:

class Order {
CustomerId;
...
CalculateDiscount();
}
class Customer {
Id;
Name;
Age;

IsStudent();
}

There are times within the application logic (on the write side), where a dependent aggregate needs to be loaded so that various items are checked. For example, even though the Order aggregate root is loosely coupled from the Customer and can be acted upon (persisted, invariants being maintained) individually, there are cases where business related to the customer needs to be checked. For example, when creating an order, the existence of the Customer must be first validated. Furthermore, as described in the small example, for calculating a discount, loading the customer and checking if they are a student would be a necessary step.

In order to do this, I have two solutions, but both have their pros and cons and I would like some opinions as to what is best (or if there are other alternatives).

Injecting the Customer write repository within the order command handler: Pro Seems to be more object oriented and enables business logic to be encapsulated within domain models. In the example above, the CalculateDiscount method can become CalculateDiscount(lCustomerWriteRepository) which encapsulates this logic within the aggregate.

Cons Apart from being able to retrieve the CustomerDomainModel the interface leaks methods to persist a CustomerDomainModel, which is a non-readonly operation that should only be done through handlers of CustomerCommands and not OrderCommands Refactoring the customer aggregate to a different service would lead to the logic being moved at a handler level

Injecting the Customer read repository within the command handler:

Pro The interface allows only readonly access to customers Read repository can be easily switched with proxy to other microservice if aggregate is separated to other microservice (As both read repository and communication over HTTP results in DTOs rather than domain model representations) Cons Logic involving calls to other aggregates is achieved at handler level. I prefer pushing as much logic towards the aggregates as possible. Changing UI requirements might affect DTOs being used in write operations and more and more unnecessary data might be fetched Aggregates are more anemic in business logic as opposed to the alternate solution.

I am hoping to find a solution to my above problem and perhaps understand what I am missing. Also, as a bonus question, I am failing to understand how Domain Services would come into play in such an architecture :)

In my code let's say I have a function which does most of the work:

def compute(x=3, y=5):
    ...

And I have a CLI wrapper program using argparse. I intend end users to use the CLI program and not the function directly, but also other developers may work on the source code. Argparse has the capability to add default arguments as command line arguments. I want to avoid duplicating specifying the defaults. Should default values be specified in the function definition, or the CLI wrapper?